Skip to content

Latest commit

 

History

History
662 lines (467 loc) · 24.6 KB

File metadata and controls

662 lines (467 loc) · 24.6 KB

What's new in Python 3.15

Editor:TBD

This article explains the new features in Python 3.15, compared to 3.14.

For full details, see the :ref:`changelog <changelog>`.

Note

Prerelease users should be aware that this document is currently in draft form. It will be updated substantially as Python 3.15 moves towards release, so it's worth checking back even after reading earlier versions.

Summary --- release highlights

New features

High frequency statistical sampling profiler

A new statistical sampling profiler has been added to the :mod:`profile` module as :mod:`profile.sample`. This profiler enables low-overhead performance analysis of running Python processes without requiring code modification or process restart.

Unlike deterministic profilers (:mod:`cProfile` and :mod:`profile`) that instrument every function call, the sampling profiler periodically captures stack traces from running processes. This approach provides virtually zero overhead while achieving sampling rates of up to 1,000,000 Hz, making it the fastest sampling profiler available for Python (at the time of its contribution) and ideal for debugging performance issues in production environments.

Key features include:

  • Zero-overhead profiling: Attach to any running Python process without affecting its performance
  • No code modification required: Profile existing applications without restart
  • Real-time statistics: Monitor sampling quality during data collection
  • Multiple output formats: Generate both detailed statistics and flamegraph data
  • Thread-aware profiling: Option to profile all threads or just the main thread

Profile process 1234 for 10 seconds with default settings:

python -m profile.sample 1234

Profile with custom interval and duration, save to file:

python -m profile.sample -i 50 -d 30 -o profile.stats 1234

Generate collapsed stacks for flamegraph:

python -m profile.sample --collapsed 1234

Profile all threads and sort by total time:

python -m profile.sample -a --sort-tottime 1234

The profiler generates statistical estimates of where time is spent:

Real-time sampling stats: Mean: 100261.5Hz (9.97µs) Min: 86333.4Hz (11.58µs) Max: 118807.2Hz (8.42µs) Samples: 400001
Captured 498841 samples in 5.00 seconds
Sample rate: 99768.04 samples/sec
Error rate: 0.72%
Profile Stats:
      nsamples   sample%   tottime (s)    cumul%   cumtime (s)  filename:lineno(function)
      43/418858       0.0         0.000      87.9         4.189  case.py:667(TestCase.run)
    3293/418812       0.7         0.033      87.9         4.188  case.py:613(TestCase._callTestMethod)
  158562/158562      33.3         1.586      33.3         1.586  test_compile.py:725(TestSpecifics.test_compiler_recursion_limit.<locals>.check_limit)
  129553/129553      27.2         1.296      27.2         1.296  ast.py:46(parse)
      0/128129       0.0         0.000      26.9         1.281  test_ast.py:884(AST_Tests.test_ast_recursion_limit.<locals>.check_limit)
        7/67446       0.0         0.000      14.2         0.674  test_compile.py:729(TestSpecifics.test_compiler_recursion_limit)
        6/60380       0.0         0.000      12.7         0.604  test_ast.py:888(AST_Tests.test_ast_recursion_limit)
        3/50020       0.0         0.000      10.5         0.500  test_compile.py:727(TestSpecifics.test_compiler_recursion_limit)
        1/38011       0.0         0.000       8.0         0.380  test_ast.py:886(AST_Tests.test_ast_recursion_limit)
        1/25076       0.0         0.000       5.3         0.251  test_compile.py:728(TestSpecifics.test_compiler_recursion_limit)
    22361/22362       4.7         0.224       4.7         0.224  test_compile.py:1368(TestSpecifics.test_big_dict_literal)
        4/18008       0.0         0.000       3.8         0.180  test_ast.py:889(AST_Tests.test_ast_recursion_limit)
      11/17696       0.0         0.000       3.7         0.177  subprocess.py:1038(Popen.__init__)
    16968/16968       3.6         0.170       3.6         0.170  subprocess.py:1900(Popen._execute_child)
        2/16941       0.0         0.000       3.6         0.169  test_compile.py:730(TestSpecifics.test_compiler_recursion_limit)

Legend:
  nsamples: Direct/Cumulative samples (direct executing / on call stack)
  sample%: Percentage of total samples this function was directly executing
  tottime: Estimated total time spent directly in this function
  cumul%: Percentage of total samples when this function was on the call stack
  cumtime: Estimated cumulative time (including time in called functions)
  filename:lineno(function): Function location and name

Summary of Interesting Functions:

Functions with Highest Direct/Cumulative Ratio (Hot Spots):
  1.000 direct/cumulative ratio, 33.3% direct samples: test_compile.py:(TestSpecifics.test_compiler_recursion_limit.<locals>.check_limit)
  1.000 direct/cumulative ratio, 27.2% direct samples: ast.py:(parse)
  1.000 direct/cumulative ratio, 3.6% direct samples: subprocess.py:(Popen._execute_child)

Functions with Highest Call Frequency (Indirect Calls):
  418815 indirect calls, 87.9% total stack presence: case.py:(TestCase.run)
  415519 indirect calls, 87.9% total stack presence: case.py:(TestCase._callTestMethod)
  159470 indirect calls, 33.5% total stack presence: test_compile.py:(TestSpecifics.test_compiler_recursion_limit)

Functions with Highest Call Magnification (Cumulative/Direct):
  12267.9x call magnification, 159470 indirect calls from 13 direct: test_compile.py:(TestSpecifics.test_compiler_recursion_limit)
  10581.7x call magnification, 116388 indirect calls from 11 direct: test_ast.py:(AST_Tests.test_ast_recursion_limit)
  9740.9x call magnification, 418815 indirect calls from 43 direct: case.py:(TestCase.run)

The profiler automatically identifies performance bottlenecks through statistical analysis, highlighting functions with high CPU usage and call frequency patterns.

This capability is particularly valuable for debugging performance issues in production systems where traditional profiling approaches would be too intrusive.

(Contributed by Pablo Galindo and László Kiss Kollár in :gh:`135953`.)

Other language changes

  • Python now uses UTF-8 as the default encoding, independent of the system's environment. This means that I/O operations without an explicit encoding, e.g. open('flying-circus.txt'), will use UTF-8. UTF-8 is a widely-supported Unicode character encoding that has become a de facto standard for representing text, including nearly every webpage on the internet, many common file formats, programming languages, and more.

    This only applies when no encoding argument is given. For best compatibility between versions of Python, ensure that an explicit encoding argument is always provided. The :ref:`opt-in encoding warning <io-encoding-warning>` can be used to identify code that may be affected by this change. The special encoding='locale' argument uses the current locale encoding, and has been supported since Python 3.10.

    To retain the previous behaviour, Python's UTF-8 mode may be disabled with the :envvar:`PYTHONUTF8=0 <PYTHONUTF8>` environment variable or the :option:`-X utf8=0 <-X>` command line option.

    .. seealso:: :pep:`686` for further details.
    
    

    (Contributed by Adam Turner in :gh:`133711`; PEP 686 written by Inada Naoki.)

  • Several error messages incorrectly using the term "argument" have been corrected. (Contributed by Stan Ulbrych in :gh:`133382`.)

  • Unraisable exceptions are now highlighted with color by default. This can be controlled by :ref:`environment variables <using-on-controlling-color>`. (Contributed by Peter Bierma in :gh:`134170`.)

New modules

  • None yet.

Improved modules

dbm

difflib

hashlib

  • Ensure that hash functions guaranteed to be always available exist as attributes of :mod:`hashlib` even if they will not work at runtime due to missing backend implementations. For instance, hashlib.md5 will no longer raise :exc:`AttributeError` if OpenSSL is not available and Python has been built without MD5 support. (Contributed by Bénédikt Tran in :gh:`136929`.)

http.client

math

os.path

shelve

sqlite3

ssl

  • Indicate through :data:`ssl.HAS_PSK_TLS13` whether the :mod:`ssl` module supports "External PSKs" in TLSv1.3, as described in RFC 9258. (Contributed by Will Childs-Klein in :gh:`133624`.)

  • Added new methods for managing groups used for SSL key agreement

    • :meth:`ssl.SSLContext.set_groups` sets the groups allowed for doing key agreement, extending the previous :meth:`ssl.SSLContext.set_ecdh_curve` method. This new API provides the ability to list multiple groups and supports fixed-field and post-quantum groups in addition to ECDH curves. This method can also be used to control what key shares are sent in the TLS handshake.
    • :meth:`ssl.SSLSocket.group` returns the group selected for doing key agreement on the current connection after the TLS handshake completes. This call requires OpenSSL 3.2 or later.
    • :meth:`ssl.SSLContext.get_groups` returns a list of all available key agreement groups compatible with the minimum and maximum TLS versions currently set in the context. This call requires OpenSSL 3.5 or later.

    (Contributed by Ron Frederick in :gh:`136306`)

tarfile

types

unittest

zlib

Optimizations

module_name

  • TODO

Deprecated

hashlib

  • In hash function constructors such as :func:`~hashlib.new` or the direct hash-named constructors such as :func:`~hashlib.md5` and :func:`~hashlib.sha256`, their optional initial data parameter could also be passed a keyword argument named data= or string= in various :mod:`hashlib` implementations.

    Support for the string keyword argument name is now deprecated and is slated for removal in Python 3.19. Prefer passing the initial data as a positional argument for maximum backwards compatibility.

    (Contributed by Bénédikt Tran in :gh:`134978`.)

Removed

ast

ctypes

glob

http.server

pathlib

platform

sre_*

sysconfig

threading

  • Remove support for arbitrary positional or keyword arguments in the C implementation of :class:`~threading.RLock` objects. This was deprecated in Python 3.14. (Contributed by Bénédikt Tran in :gh:`134087`.)

typing

  • The undocumented keyword argument syntax for creating :class:`~typing.NamedTuple` classes (for example, Point = NamedTuple("Point", x=int, y=int)) is no longer supported. Use the class-based syntax or the functional syntax instead. (Contributed by Bénédikt Tran in :gh:`133817`.)
  • Using TD = TypedDict("TD") or TD = TypedDict("TD", None) to construct a :class:`~typing.TypedDict` type with zero field is no longer supported. Use class TD(TypedDict): pass or TD = TypedDict("TD", {}) instead. (Contributed by Bénédikt Tran in :gh:`133823`.)
  • Code like class ExtraTypeVars(P1[S], Protocol[T, T2]): ... now raises a :exc:`TypeError`, because S is not listed in Protocol parameters. (Contributed by Nikita Sobolev in :gh:`137191`.)
  • Code like class B2(A[T2], Protocol[T1, T2]): ... now correctly handles type parameters order: it is (T1, T2), not (T2, T1) as it was incorrectly infered in runtime before. (Contributed by Nikita Sobolev in :gh:`137191`.)

wave

Porting to Python 3.15

This section lists previously described changes and other bugfixes that may require changes to your code.

Build changes

C API changes

New features

Porting to Python 3.15

Deprecated C APIs

Removed C APIs

The following functions are removed in favor of :c:func:`PyConfig_Get`. The pythoncapi-compat project can be used to get :c:func:`!PyConfig_Get` on Python 3.13 and older.