Skip to content

Latest commit

 

History

History
2848 lines (2087 loc) · 106 KB

File metadata and controls

2848 lines (2087 loc) · 106 KB

What's new in Python 3.14

Editor:Hugo van Kemenade

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

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

.. seealso::

   :pep:`745` -- Python 3.14 release schedule

Note

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

Summary -- release highlights

Python 3.14 beta is the pre-release of the next version of the Python programming language, with a mix of changes to the language, the implementation and the standard library.

The biggest changes to the implementation include template strings (PEP 750), deferred evaluation of annotations (PEP 649), and a new type of interpreter that uses tail calls.

The library changes include the addition of a new :mod:`!annotationlib` module for introspecting and wrapping annotations (PEP 649), a new :mod:`!compression.zstd` module for Zstandard support (PEP 784), plus syntax highlighting in the REPL, as well as the usual deprecations and removals, and improvements in user-friendliness and correctness.

Incompatible changes

On platforms other than macOS and Windows, the default :ref:`start method <multiprocessing-start-methods>` for :mod:`multiprocessing` and :class:`~concurrent.futures.ProcessPoolExecutor` switches from fork to forkserver.

See :ref:`(1) <whatsnew314-concurrent-futures-start-method>` and :ref:`(2) <whatsnew314-multiprocessing-start-method>` for details.

If you encounter :exc:`NameError`s or pickling errors coming out of :mod:`multiprocessing` or :mod:`concurrent.futures`, see the :ref:`forkserver restrictions <multiprocessing-programming-forkserver>`.

The interpreter avoids some reference count modifications internally when it's safe to do so. This can lead to different values returned from :func:`sys.getrefcount` and :c:func:`Py_REFCNT` compared to previous versions of Python. See :ref:`below <whatsnew314-refcount>` for details.

New features

PEP 750: Template strings

Template string literals (t-strings) are a generalization of f-strings, using a t in place of the f prefix. Instead of evaluating to :class:`str`, t-strings evaluate to a new :class:`!string.templatelib.Template` type:

from string.templatelib import Template

name = "World"
template: Template = t"Hello {name}"

The template can then be combined with functions that operate on the template's structure to produce a :class:`str` or a string-like result. For example, sanitizing input:

evil = "<script>alert('evil')</script>"
template = t"<p>{evil}</p>"
assert html(template) == "<p>&lt;script&gt;alert('evil')&lt;/script&gt;</p>"

As another example, generating HTML attributes from data:

attributes = {"src": "shrubbery.jpg", "alt": "looks nice"}
template = t"<img {attributes}>"
assert html(template) == '<img src="shrubbery.jpg" alt="looks nice" class="looks-nice">'

Compared to using an f-string, the html function has access to template attributes containing the original information: static strings, interpolations, and values from the original scope. Unlike existing templating approaches, t-strings build from the well-known f-string syntax and rules. Template systems thus benefit from Python tooling as they are much closer to the Python language, syntax, scoping, and more.

Writing template handlers is straightforward:

from string.templatelib import Template, Interpolation

def lower_upper(template: Template) -> str:
    """Render static parts lowercased and interpolations uppercased."""
    parts: list[str] = []
    for item in template:
        if isinstance(item, Interpolation):
            parts.append(str(item.value).upper())
        else:
            parts.append(item.lower())
    return "".join(parts)

name = "world"
assert lower_upper(t"HELLO {name}") == "hello WORLD"

With this in place, developers can write template systems to sanitize SQL, make safe shell operations, improve logging, tackle modern ideas in web development (HTML, CSS, and so on), and implement lightweight, custom business DSLs.

(Contributed by Jim Baker, Guido van Rossum, Paul Everitt, Koudai Aono, Lysandros Nikolaou, Dave Peck, Adam Turner, Jelle Zijlstra, Bénédikt Tran, and Pablo Galindo Salgado in :gh:`132661`.)

.. seealso::
   :pep:`750`.


PEP 768: Safe external debugger interface for CPython

PEP 768 introduces a zero-overhead debugging interface that allows debuggers and profilers to safely attach to running Python processes. This is a significant enhancement to Python's debugging capabilities allowing debuggers to forego unsafe alternatives. See :ref:`below <whatsnew314-remote-pdb>` for how this feature is leveraged to implement the new :mod:`pdb` module's remote attaching capabilities.

The new interface provides safe execution points for attaching debugger code without modifying the interpreter's normal execution path or adding runtime overhead. This enables tools to inspect and interact with Python applications in real-time without stopping or restarting them — a crucial capability for high-availability systems and production environments.

For convenience, CPython implements this interface through the :mod:`sys` module with a :func:`sys.remote_exec` function:

sys.remote_exec(pid, script_path)

This function allows sending Python code to be executed in a target process at the next safe execution point. However, tool authors can also implement the protocol directly as described in the PEP, which details the underlying mechanisms used to safely attach to running processes.

Here's a simple example that inspects object types in a running Python process:

import os
import sys
import tempfile

# Create a temporary script
with tempfile.NamedTemporaryFile(mode='w', suffix='.py', delete=False) as f:
    script_path = f.name
    f.write(f"import my_debugger; my_debugger.connect({os.getpid()})")
try:
    # Execute in process with PID 1234
    print("Behold! An offering:")
    sys.remote_exec(1234, script_path)
finally:
    os.unlink(script_path)

The debugging interface has been carefully designed with security in mind and includes several mechanisms to control access:

A key implementation detail is that the interface piggybacks on the interpreter's existing evaluation loop and safe points, ensuring zero overhead during normal execution while providing a reliable way for external processes to coordinate debugging operations.

(Contributed by Pablo Galindo Salgado, Matt Wozniski, and Ivona Stojanovic in :gh:`131591`.)

.. seealso::
   :pep:`768`.


PEP 784: Adding Zstandard to the standard library

The new compression package contains modules :mod:`!compression.lzma`, :mod:`!compression.bz2`, :mod:`!compression.gzip` and :mod:`!compression.zlib` which re-export the :mod:`lzma`, :mod:`bz2`, :mod:`gzip` and :mod:`zlib` modules respectively. The new import names under compression are the canonical names for importing these compression modules going forward. However, the existing modules names have not been deprecated. Any deprecation or removal of the existing compression modules will occur no sooner than five years after the release of 3.14.

The new :mod:`!compression.zstd` module provides compression and decompression APIs for the Zstandard format via bindings to Meta's zstd library. Zstandard is a widely adopted, highly efficient, and fast compression format. In addition to the APIs introduced in :mod:`!compression.zstd`, support for reading and writing Zstandard compressed archives has been added to the :mod:`tarfile`, :mod:`zipfile`, and :mod:`shutil` modules.

Here's an example of using the new module to compress some data:

from compression import zstd
import math

data = str(math.pi).encode() * 20

compressed = zstd.compress(data)

ratio = len(compressed) / len(data)
print(f"Achieved compression ratio of {ratio}")

As can be seen, the API is similar to the APIs of the :mod:`!lzma` and :mod:`!bz2` modules.

(Contributed by Emma Harper Smith, Adam Turner, Gregory P. Smith, Tomas Roun, Victor Stinner, and Rogdham in :gh:`132983`)

.. seealso::
   :pep:`784`.


Remote attaching to a running Python process with PDB

The :mod:`pdb` module now supports remote attaching to a running Python process using a new -p PID command-line option:

python -m pdb -p 1234

This will connect to the Python process with the given PID and allow you to debug it interactively. Notice that due to how the Python interpreter works attaching to a remote process that is blocked in a system call or waiting for I/O will only work once the next bytecode instruction is executed or when the process receives a signal.

This feature uses PEP 768 and the :func:`sys.remote_exec` function to attach to the remote process and send the PDB commands to it.

(Contributed by Matt Wozniski and Pablo Galindo in :gh:`131591`.)

.. seealso::
   :pep:`768`.


PEP 758 – Allow except and except* expressions without parentheses

The :keyword:`except` and :keyword:`except* <except_star>` expressions now allow parentheses to be omitted when there are multiple exception types and the as clause is not used. For example the following expressions are now valid:

try:
    release_new_sleep_token_album()
except AlbumNotFound, SongsTooGoodToBeReleased:
    print("Sorry, no new album this year.")

 # The same applies to except* (for exception groups):
try:
    release_new_sleep_token_album()
except* AlbumNotFound, SongsTooGoodToBeReleased:
    print("Sorry, no new album this year.")

Check PEP 758 for more details.

(Contributed by Pablo Galindo and Brett Cannon in :gh:`131831`.)

.. seealso::
   :pep:`758`.


PEP 649 and 749: deferred evaluation of annotations

The :term:`annotations <annotation>` on functions, classes, and modules are no longer evaluated eagerly. Instead, annotations are stored in special-purpose :term:`annotate functions <annotate function>` and evaluated only when necessary (except if from __future__ import annotations is used). This is specified in PEP 649 and PEP 749.

This change is designed to make annotations in Python more performant and more usable in most circumstances. The runtime cost for defining annotations is minimized, but it remains possible to introspect annotations at runtime. It is no longer necessary to enclose annotations in strings if they contain forward references.

The new :mod:`annotationlib` module provides tools for inspecting deferred annotations. Annotations may be evaluated in the :attr:`~annotationlib.Format.VALUE` format (which evaluates annotations to runtime values, similar to the behavior in earlier Python versions), the :attr:`~annotationlib.Format.FORWARDREF` format (which replaces undefined names with special markers), and the :attr:`~annotationlib.Format.STRING` format (which returns annotations as strings).

This example shows how these formats behave:

>>> from annotationlib import get_annotations, Format
>>> def func(arg: Undefined):
...     pass
>>> get_annotations(func, format=Format.VALUE)
Traceback (most recent call last):
  ...
NameError: name 'Undefined' is not defined
>>> get_annotations(func, format=Format.FORWARDREF)
{'arg': ForwardRef('Undefined', owner=<function func at 0x...>)}
>>> get_annotations(func, format=Format.STRING)
{'arg': 'Undefined'}

Implications for annotated code

If you define annotations in your code (for example, for use with a static type checker), then this change probably does not affect you: you can keep writing annotations the same way you did with previous versions of Python.

You will likely be able to remove quoted strings in annotations, which are frequently used for forward references. Similarly, if you use from __future__ import annotations to avoid having to write strings in annotations, you may well be able to remove that import once you support only Python 3.14 and newer. However, if you rely on third-party libraries that read annotations, those libraries may need changes to support unquoted annotations before they work as expected.

Implications for readers of __annotations__

If your code reads the __annotations__ attribute on objects, you may want to make changes in order to support code that relies on deferred evaluation of annotations. For example, you may want to use :func:`annotationlib.get_annotations` with the :attr:`~annotationlib.Format.FORWARDREF` format, as the :mod:`dataclasses` module now does.

The external :pypi:`typing_extensions` package provides partial backports of some of the functionality of the :mod:`annotationlib` module, such as the :class:`~annotationlib.Format` enum and the :func:`~annotationlib.get_annotations` function. These can be used to write cross-version code that takes advantage of the new behavior in Python 3.14.

Related changes

The changes in Python 3.14 are designed to rework how __annotations__ works at runtime while minimizing breakage to code that contains annotations in source code and to code that reads __annotations__. However, if you rely on undocumented details of the annotation behavior or on private functions in the standard library, there are many ways in which your code may not work in Python 3.14. To safeguard your code against future changes, use only the documented functionality of the :mod:`annotationlib` module.

In particular, do not read annotations directly from the namespace dictionary attribute of type objects. Use :func:`annotationlib.get_annotate_from_class_namespace` during class construction and :func:`annotationlib.get_annotations` afterwards.

from __future__ import annotations

In Python 3.7, PEP 563 introduced the from __future__ import annotations directive, which turns all annotations into strings. This directive is now considered deprecated and it is expected to be removed in a future version of Python. However, this removal will not happen until after Python 3.13, the last version of Python without deferred evaluation of annotations, reaches its end of life in 2029. In Python 3.14, the behavior of code using from __future__ import annotations is unchanged.

(Contributed by Jelle Zijlstra in :gh:`119180`; PEP 649 was written by Larry Hastings.)

.. seealso::
   :pep:`649` and :pep:`749`.


Improved error messages

  • The interpreter now provides helpful suggestions when it detects typos in Python keywords. When a word that closely resembles a Python keyword is encountered, the interpreter will suggest the correct keyword in the error message. This feature helps programmers quickly identify and fix common typing mistakes. For example:

    >>> whille True:
    ...     pass
    Traceback (most recent call last):
      File "<stdin>", line 1
        whille True:
        ^^^^^^
    SyntaxError: invalid syntax. Did you mean 'while'?
    
    >>> asynch def fetch_data():
    ...     pass
    Traceback (most recent call last):
      File "<stdin>", line 1
        asynch def fetch_data():
        ^^^^^^
    SyntaxError: invalid syntax. Did you mean 'async'?
    
    >>> async def foo():
    ...     awaid fetch_data()
    Traceback (most recent call last):
      File "<stdin>", line 2
        awaid fetch_data()
        ^^^^^
    SyntaxError: invalid syntax. Did you mean 'await'?
    
    >>> raisee ValueError("Error")
    Traceback (most recent call last):
      File "<stdin>", line 1
        raisee ValueError("Error")
        ^^^^^^
    SyntaxError: invalid syntax. Did you mean 'raise'?

    While the feature focuses on the most common cases, some variations of misspellings may still result in regular syntax errors. (Contributed by Pablo Galindo in :gh:`132449`.)

  • When unpacking assignment fails due to incorrect number of variables, the error message prints the received number of values in more cases than before. (Contributed by Tushar Sadhwani in :gh:`122239`.)

    >>> x, y, z = 1, 2, 3, 4
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
        x, y, z = 1, 2, 3, 4
        ^^^^^^^
    ValueError: too many values to unpack (expected 3, got 4)
  • :keyword:`elif` statements that follow an :keyword:`else` block now have a specific error message. (Contributed by Steele Farnsworth in :gh:`129902`.)

    >>> if who == "me":
    ...     print("It's me!")
    ... else:
    ...     print("It's not me!")
    ... elif who is None:
    ...     print("Who is it?")
    File "<stdin>", line 5
      elif who is None:
      ^^^^
    SyntaxError: 'elif' block follows an 'else' block
  • If a statement (:keyword:`pass`, :keyword:`del`, :keyword:`return`, :keyword:`yield`, :keyword:`raise`, :keyword:`break`, :keyword:`continue`, :keyword:`assert`, :keyword:`import`, :keyword:`from`) is passed to the :ref:`if_expr` after :keyword:`else`, or one of :keyword:`pass`, :keyword:`break`, or :keyword:`continue` is passed before :keyword:`if`, then the error message highlights where the :token:`~python-grammar:expression` is required. (Contributed by Sergey Miryanov in :gh:`129515`.)

    >>> x = 1 if True else pass
    Traceback (most recent call last):
      File "<string>", line 1
        x = 1 if True else pass
                           ^^^^
    SyntaxError: expected expression after 'else', but statement is given
    
    >>> x = continue if True else break
    Traceback (most recent call last):
      File "<string>", line 1
        x = continue if True else break
            ^^^^^^^^
    SyntaxError: expected expression before 'if', but statement is given
  • When incorrectly closed strings are detected, the error message suggests that the string may be intended to be part of the string. (Contributed by Pablo Galindo in :gh:`88535`.)

    >>> "The interesting object "The important object" is very important"
    Traceback (most recent call last):
    SyntaxError: invalid syntax. Is this intended to be part of the string?
  • When strings have incompatible prefixes, the error now shows which prefixes are incompatible. (Contributed by Nikita Sobolev in :gh:`133197`.)

    >>> ub'abc'
      File "<python-input-0>", line 1
        ub'abc'
        ^^
    SyntaxError: 'u' and 'b' prefixes are incompatible
  • Improved error messages when using as with incompatible targets in:

    • Imports: import ... as ...
    • From imports: from ... import ... as ...
    • Except handlers: except ... as ...
    • Pattern-match cases: case ... as ...

    (Contributed by Nikita Sobolev in :gh:`123539`, :gh:`123562`, and :gh:`123440`.)

    >>> import ast as arr[0]
      File "<python-input-1>", line 1
        import ast as arr[0]
                      ^^^^^^
    SyntaxError: cannot use subscript as import target
  • Improved error message when trying to add an instance of an unhashable type to a :class:`dict` or :class:`set`. (Contributed by CF Bolz-Tereick and Victor Stinner in :gh:`132828`.)

    >>> s = set()
    >>> s.add({'pages': 12, 'grade': 'A'})
    Traceback (most recent call last):
      File "<python-input-1>", line 1, in <module>
        s.add({'pages': 12, 'grade': 'A'})
        ~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    TypeError: cannot use 'dict' as a set element (unhashable type: 'dict')
    >>> d = {}
    >>> l = [1, 2, 3]
    >>> d[l] = 12
    Traceback (most recent call last):
      File "<python-input-4>", line 1, in <module>
        d[l] = 12
        ~^^^
    TypeError: cannot use 'list' as a dict key (unhashable type: 'list')

PEP 741: Python Configuration C API

Add a :ref:`PyInitConfig C API <pyinitconfig_api>` to configure the Python initialization without relying on C structures and the ability to make ABI-compatible changes in the future.

Complete the PEP 587 :ref:`PyConfig C API <pyconfig_api>` by adding :c:func:`PyInitConfig_AddModule` which can be used to add a built-in extension module; feature previously referred to as the “inittab”.

Add :c:func:`PyConfig_Get` and :c:func:`PyConfig_Set` functions to get and set the current runtime configuration.

PEP 587 “Python Initialization Configuration” unified all the ways to configure the Python initialization. This PEP unifies also the configuration of the Python preinitialization and the Python initialization in a single API. Moreover, this PEP only provides a single choice to embed Python, instead of having two “Python” and “Isolated” choices (PEP 587), to simplify the API further.

The lower level PEP 587 PyConfig API remains available for use cases with an intentionally higher level of coupling to CPython implementation details (such as emulating the full functionality of CPython’s CLI, including its configuration mechanisms).

(Contributed by Victor Stinner in :gh:`107954`.)

.. seealso::
   :pep:`741`.

Asyncio introspection capabilities

Added a new command-line interface to inspect running Python processes using asynchronous tasks, available via:

python -m asyncio ps PID

This tool inspects the given process ID (PID) and displays information about currently running asyncio tasks. It outputs a task table: a flat listing of all tasks, their names, their coroutine stacks, and which tasks are awaiting them.

python -m asyncio pstree PID

This tool fetches the same information, but renders a visual async call tree, showing coroutine relationships in a hierarchical format. This command is particularly useful for debugging long-running or stuck asynchronous programs. It can help developers quickly identify where a program is blocked, what tasks are pending, and how coroutines are chained together.

For example given this code:

import asyncio

async def play(track):
    await asyncio.sleep(5)
    print(f"🎵 Finished: {track}")

async def album(name, tracks):
    async with asyncio.TaskGroup() as tg:
        for track in tracks:
            tg.create_task(play(track), name=track)

async def main():
    async with asyncio.TaskGroup() as tg:
        tg.create_task(
          album("Sundowning", ["TNDNBTG", "Levitate"]), name="Sundowning")
        tg.create_task(
          album("TMBTE", ["DYWTYLM", "Aqua Regia"]), name="TMBTE")

if __name__ == "__main__":
    asyncio.run(main())

Executing the new tool on the running process will yield a table like this:

python -m asyncio ps 12345

tid        task id              task name            coroutine chain                                    awaiter name         awaiter id
---------------------------------------------------------------------------------------------------------------------------------------
8138752    0x564bd3d0210        Task-1                                                                                       0x0
8138752    0x564bd3d0410        Sundowning           _aexit -> __aexit__ -> main                        Task-1               0x564bd3d0210
8138752    0x564bd3d0610        TMBTE                _aexit -> __aexit__ -> main                        Task-1               0x564bd3d0210
8138752    0x564bd3d0810        TNDNBTG              _aexit -> __aexit__ -> album                       Sundowning           0x564bd3d0410
8138752    0x564bd3d0a10        Levitate             _aexit -> __aexit__ -> album                       Sundowning           0x564bd3d0410
8138752    0x564bd3e0550        DYWTYLM              _aexit -> __aexit__ -> album                       TMBTE                 0x564bd3d0610
8138752    0x564bd3e0710        Aqua Regia           _aexit -> __aexit__ -> album                       TMBTE                 0x564bd3d0610

or:

python -m asyncio pstree 12345

└── (T) Task-1
    └──  main
        └──  __aexit__
            └──  _aexit
                ├── (T) Sundowning
                │   └──  album
                │       └──  __aexit__
                │           └──  _aexit
                │               ├── (T) TNDNBTG
                │               └── (T) Levitate
                └── (T) TMBTE
                    └──  album
                        └──  __aexit__
                            └──  _aexit
                                ├── (T) DYWTYLM
                                └── (T) Aqua Regia

If a cycle is detected in the async await graph (which could indicate a programming issue), the tool raises an error and lists the cycle paths that prevent tree construction.

(Contributed by Pablo Galindo, Łukasz Langa, Yury Selivanov, and Marta Gomez Macias in :gh:`91048`.)

A new type of interpreter

A new type of interpreter has been added to CPython. It uses tail calls between small C functions that implement individual Python opcodes, rather than one large C case statement. For certain newer compilers, this interpreter provides significantly better performance. Preliminary numbers on our machines suggest anywhere up to 30% faster Python code, and a geometric mean of 3-5% faster on pyperformance depending on platform and architecture. The baseline is Python 3.14 built with Clang 19 without this new interpreter.

This interpreter currently only works with Clang 19 and newer on x86-64 and AArch64 architectures. However, we expect that a future release of GCC will support this as well.

This feature is opt-in for now. We highly recommend enabling profile-guided optimization with the new interpreter as it is the only configuration we have tested and can validate its improved performance. For further information on how to build Python, see :option:`--with-tail-call-interp`.

Note

This is not to be confused with tail call optimization of Python functions, which is currently not implemented in CPython.

This new interpreter type is an internal implementation detail of the CPython interpreter. It doesn't change the visible behavior of Python programs at all. It can improve their performance, but doesn't change anything else.

Attention!

This section previously reported a 9-15% geometric mean speedup. This number has since been cautiously revised down to 3-5%. While we expect performance results to be better than what we report, our estimates are more conservative due to a compiler bug found in Clang/LLVM 19, which causes the normal interpreter to be slower. We were unaware of this bug, resulting in inaccurate results. We sincerely apologize for communicating results that were only accurate for LLVM v19.1.x and v20.1.0. In the meantime, the bug has been fixed in LLVM v20.1.1 and for the upcoming v21.1, but it will remain unfixed for LLVM v19.1.x and v20.1.0. Thus any benchmarks with those versions of LLVM may produce inaccurate numbers. (Thanks to Nelson Elhage for bringing this to light.)

(Contributed by Ken Jin in :gh:`128563`, with ideas on how to implement this in CPython by Mark Shannon, Garrett Gu, Haoran Xu, and Josh Haberman.)

Free-threaded mode

Free-threaded mode (PEP 703), initially added in 3.13, has been significantly improved. The implementation described in PEP 703 was finished, including C API changes, and temporary workarounds in the interpreter were replaced with more permanent solutions. The specializing adaptive interpreter (PEP 659) is now enabled in free-threaded mode, which along with many other optimizations greatly improves its performance. The performance penalty on single-threaded code in free-threaded mode is now roughly 5-10%, depending on platform and C compiler used.

This work was done by many contributors: Sam Gross, Matt Page, Neil Schemenauer, Thomas Wouters, Donghee Na, Kirill Podoprigora, Ken Jin, Itamar Oren, Brett Simmers, Dino Viehland, Nathan Goldbaum, Ralf Gommers, Lysandros Nikolaou, Kumar Aditya, Edgar Margffoy, and many others.

Some of these contributors are employed by Meta, which has continued to provide significant engineering resources to support this project.

From 3.14, when compiling extension modules for the free-threaded build of CPython on Windows, the preprocessor variable Py_GIL_DISABLED now needs to be specified by the build backend, as it will no longer be determined automatically by the C compiler. For a running interpreter, the setting that was used at compile time can be found using :func:`sysconfig.get_config_var`.

Syntax highlighting in PyREPL

The default :term:`interactive` shell now highlights Python syntax as you type. The feature is enabled by default unless the :envvar:`PYTHON_BASIC_REPL` environment is set or any color-disabling environment variables are used. See :ref:`using-on-controlling-color` for details.

The default color theme for syntax highlighting strives for good contrast and uses exclusively the 4-bit VGA standard ANSI color codes for maximum compatibility. The theme can be customized using an experimental API _colorize.set_theme(). This can be called interactively, as well as in the :envvar:`PYTHONSTARTUP` script.

(Contributed by Łukasz Langa in :gh:`131507`.)

Binary releases for the experimental just-in-time compiler

The official macOS and Windows release binaries now include an experimental just-in-time (JIT) compiler. Although it is not recommended for production use, it can be tested by setting :envvar:`PYTHON_JIT=1 <PYTHON_JIT>` as an environment variable. Downstream source builds and redistributors can use the :option:`--enable-experimental-jit=yes-off` configuration option for similar behavior.

The JIT is at an early stage and still in active development. As such, the typical performance impact of enabling it can range from 10% slower to 20% faster, depending on workload. To aid in testing and evaluation, a set of introspection functions has been provided in the :data:`sys._jit` namespace. :func:`sys._jit.is_available` can be used to determine if the current executable supports JIT compilation, while :func:`sys._jit.is_enabled` can be used to tell if JIT compilation has been enabled for the current process.

Currently, the most significant missing functionality is that native debuggers and profilers like gdb and perf are unable to unwind through JIT frames (Python debuggers and profilers, like :mod:`pdb` or :mod:`profile`, continue to work without modification). Free-threaded builds do not support JIT compilation.

Please report any bugs or major performance regressions that you encounter!

.. seealso:: :pep:`744`


Other language changes

  • The default :term:`interactive` shell now supports import autocompletion. This means that typing import foo and pressing <tab> will suggest modules starting with foo. Similarly, typing from foo import b will suggest submodules of foo starting with b. Note that autocompletion of module attributes is not currently supported. (Contributed by Tomas Roun in :gh:`69605`.)
  • The :func:`map` built-in now has an optional keyword-only strict flag like :func:`zip` to check that all the iterables are of equal length. (Contributed by Wannes Boeykens in :gh:`119793`.)
  • Incorrect usage of :keyword:`await` and asynchronous comprehensions is now detected even if the code is optimized away by the :option:`-O` command-line option. For example, python -O -c 'assert await 1' now produces a :exc:`SyntaxError`. (Contributed by Jelle Zijlstra in :gh:`121637`.)
  • Writes to __debug__ are now detected even if the code is optimized away by the :option:`-O` command-line option. For example, python -O -c 'assert (__debug__ := 1)' now produces a :exc:`SyntaxError`. (Contributed by Irit Katriel in :gh:`122245`.)
  • Add class methods :meth:`float.from_number` and :meth:`complex.from_number` to convert a number to :class:`float` or :class:`complex` type correspondingly. They raise an error if the argument is a string. (Contributed by Serhiy Storchaka in :gh:`84978`.)
  • Implement mixed-mode arithmetic rules combining real and complex numbers as specified by C standards since C99. (Contributed by Sergey B Kirpichev in :gh:`69639`.)
  • All Windows code pages are now supported as "cpXXX" codecs on Windows. (Contributed by Serhiy Storchaka in :gh:`123803`.)
  • :class:`super` objects are now :mod:`pickleable <pickle>` and :mod:`copyable <copy>`. (Contributed by Serhiy Storchaka in :gh:`125767`.)
  • The :class:`memoryview` type now supports subscription, making it a :term:`generic type`. (Contributed by Brian Schubert in :gh:`126012`.)
  • Support underscore and comma as thousands separators in the fractional part for floating-point presentation types of the new-style string formatting (with :func:`format` or :ref:`f-strings`). (Contributed by Sergey B Kirpichev in :gh:`87790`.)
  • The :func:`bytes.fromhex` and :func:`bytearray.fromhex` methods now accept ASCII :class:`bytes` and :term:`bytes-like objects <bytes-like object>`. (Contributed by Daniel Pope in :gh:`129349`.)
  • Support \z as a synonym for \Z in :mod:`regular expressions <re>`. It is interpreted unambiguously in many other regular expression engines, unlike \Z, which has subtly different behavior. (Contributed by Serhiy Storchaka in :gh:`133306`.)
  • \B in :mod:`regular expression <re>` now matches empty input string. Now it is always the opposite of \b. (Contributed by Serhiy Storchaka in :gh:`124130`.)
  • iOS and macOS apps can now be configured to redirect stdout and stderr content to the system log. (Contributed by Russell Keith-Magee in :gh:`127592`.)
  • The iOS testbed is now able to stream test output while the test is running. The testbed can also be used to run the test suite of projects other than CPython itself. (Contributed by Russell Keith-Magee in :gh:`127592`.)
  • Three-argument :func:`pow` now tries calling :meth:`~object.__rpow__` if necessary. Previously it was only called in two-argument :func:`!pow` and the binary power operator. (Contributed by Serhiy Storchaka in :gh:`130104`.)
  • Add a built-in implementation for HMAC (RFC 2104) using formally verified code from the HACL* project. This implementation is used as a fallback when the OpenSSL implementation of HMAC is not available. (Contributed by Bénédikt Tran in :gh:`99108`.)
  • The import time flag can now track modules that are already loaded ('cached'), via the new :option:`-X importtime=2 <-X>`. When such a module is imported, the self and cumulative times are replaced by the string cached. Values above 2 for -X importtime are now reserved for future use. (Contributed by Noah Kim and Adam Turner in :gh:`118655`.)
  • When subclassing from a pure C type, the C slots for the new type are no longer replaced with a wrapped version on class creation if they are not explicitly overridden in the subclass. (Contributed by Tomasz Pytel in :gh:`132329`.)
  • The command-line option :option:`-c` now automatically dedents its code argument before execution. The auto-dedentation behavior mirrors :func:`textwrap.dedent`. (Contributed by Jon Crall and Steven Sun in :gh:`103998`.)
  • Improve error message when an object supporting the synchronous context manager protocol is entered using :keyword:`async with` instead of :keyword:`with`. And vice versa with the asynchronous context manager protocol. (Contributed by Bénédikt Tran in :gh:`128398`.)
  • :option:`!-J` is no longer a reserved flag for Jython, and now has no special meaning. (Contributed by Adam Turner in :gh:`133336`.)

PEP 765: Disallow return/break/continue that exit a finally block

The compiler emits a :exc:`SyntaxWarning` when a :keyword:`return`, :keyword:`break` or :keyword:`continue` statements appears where it exits a :keyword:`finally` block. This change is specified in PEP 765.

New modules

Improved modules

argparse

ast

  • Add :func:`ast.compare` for comparing two ASTs. (Contributed by Batuhan Taskaya and Jeremy Hylton in :gh:`60191`.)
  • Add support for :func:`copy.replace` for AST nodes. (Contributed by Bénédikt Tran in :gh:`121141`.)
  • Docstrings are now removed from an optimized AST in optimization level 2. (Contributed by Irit Katriel in :gh:`123958`.)
  • The repr() output for AST nodes now includes more information. (Contributed by Tomas Roun in :gh:`116022`.)
  • :func:`ast.parse`, when called with an AST as input, now always verifies that the root node type is appropriate. (Contributed by Irit Katriel in :gh:`130139`.)
  • Add new --feature-version, --optimize, --show-empty options to command-line interface. (Contributed by Semyon Moroz in :gh:`133367`.)

bdb

calendar

concurrent.futures

contextvars

ctypes

curses

datetime

decimal

difflib

dis

errno

faulthandler

fnmatch

fractions

functools

getopt

  • Add support for options with optional arguments. (Contributed by Serhiy Storchaka in :gh:`126374`.)
  • Add support for returning intermixed options and non-option arguments in order. (Contributed by Serhiy Storchaka in :gh:`126390`.)

getpass

  • Support keyboard feedback by :func:`getpass.getpass` via the keyword-only optional argument echo_char. Placeholder characters are rendered whenever a character is entered, and removed when a character is deleted. (Contributed by Semyon Moroz in :gh:`77065`.)

graphlib

heapq

hmac

  • Add a built-in implementation for HMAC (RFC 2104) using formally verified code from the HACL* project. (Contributed by Bénédikt Tran in :gh:`99108`.)

http

  • Directory lists and error pages generated by the :mod:`http.server` module allow the browser to apply its default dark mode. (Contributed by Yorik Hansen in :gh:`123430`.)

  • The :mod:`http.server` module now supports serving over HTTPS using the :class:`http.server.HTTPSServer` class. This functionality is exposed by the command-line interface (python -m http.server) through the following options:

    • --tls-cert <path>: Path to the TLS certificate file.
    • --tls-key <path>: Optional path to the private key file.
    • --tls-password-file <path>: Optional path to the password file for the private key.

    (Contributed by Semyon Moroz in :gh:`85162`.)

imaplib

inspect

io

json

linecache

logging.handlers

math

  • Added more detailed error messages for domain errors in the module. (Contributed by by Charlie Zhao and Sergey B Kirpichev in :gh:`101410`.)

mimetypes

  • Document the command-line for :mod:`mimetypes`. It now exits with 1 on failure instead of 0 and 2 on incorrect command-line parameters instead of 1. Also, errors are printed to stderr instead of stdout and their text is made tighter. (Contributed by Oleg Iarygin and Hugo van Kemenade in :gh:`93096`.)

  • Add MS and RFC 8081 MIME types for fonts:

    • Embedded OpenType: application/vnd.ms-fontobject
    • OpenType Layout (OTF) font/otf
    • TrueType: font/ttf
    • WOFF 1.0 font/woff
    • WOFF 2.0 font/woff2

    (Contributed by Sahil Prajapati and Hugo van Kemenade in :gh:`84852`.)

  • Add RFC 9559 MIME types for Matroska audiovisual data container structures, containing:

    • audio with no video: audio/matroska (.mka)
    • video: video/matroska (.mkv)
    • stereoscopic video: video/matroska-3d (.mk3d)

    (Contributed by Hugo van Kemenade in :gh:`89416`.)

  • Add MIME types for images with RFCs:

    • RFC 1494: CCITT Group 3 (.g3)
    • RFC 3362: Real-time Facsimile, T.38 (.t38)
    • RFC 3745: JPEG 2000 (.jp2), extension (.jpx) and compound (.jpm)
    • RFC 3950: Tag Image File Format Fax eXtended, TIFF-FX (.tfx)
    • RFC 4047: Flexible Image Transport System (.fits)
    • RFC 7903: Enhanced Metafile (.emf) and Windows Metafile (.wmf)

    (Contributed by Hugo van Kemenade in :gh:`85957`.)

  • More MIME type changes:

    • RFC 2361: Change type for .avi to video/vnd.avi and for .wav to audio/vnd.wave
    • RFC 4337: Add MPEG-4 audio/mp4 (.m4a)
    • RFC 5334: Add Ogg media (.oga, .ogg and .ogx)
    • RFC 6713: Add gzip application/gzip (.gz)
    • RFC 9639: Add FLAC audio/flac (.flac)
    • Add 7z application/x-7z-compressed (.7z)
    • Add Android Package application/vnd.android.package-archive (.apk) when not strict
    • Add deb application/x-debian-package (.deb)
    • Add glTF binary model/gltf-binary (.glb)
    • Add glTF JSON/ASCII model/gltf+json (.gltf)
    • Add M4V video/x-m4v (.m4v)
    • Add PHP application/x-httpd-php (.php)
    • Add RAR application/vnd.rar (.rar)
    • Add RPM application/x-rpm (.rpm)
    • Add STL model/stl (.stl)
    • Add Windows Media Video video/x-ms-wmv (.wmv)
    • De facto: Add WebM audio/webm (.weba)
    • ECMA-376: Add .docx, .pptx and .xlsx types
    • OASIS: Add OpenDocument .odg, .odp, .ods and .odt types
    • W3C: Add EPUB application/epub+zip (.epub)

    (Contributed by Hugo van Kemenade in :gh:`129965`.)

  • Add RFC 9512 application/yaml MIME type for YAML files (.yaml and .yml). (Contributed by Sasha "Nelie" Chernykh and Hugo van Kemenade in :gh:`132056`.)

multiprocessing

operator

os

pathlib

pdb

pickle

platform

pydoc

socket

ssl

struct

symtable

sys

sys.monitoring

time

sysconfig

threading

tkinter

turtle

types

typing

  • :class:`types.UnionType` and :class:`typing.Union` are now aliases for each other, meaning that both old-style unions (created with Union[int, str]) and new-style unions (int | str) now create instances of the same runtime type. This unifies the behavior between the two syntaxes, but leads to some differences in behavior that may affect users who introspect types at runtime:

    • Both syntaxes for creating a union now produce the same string representation in repr(). For example, repr(Union[int, str]) is now "int | str" instead of "typing.Union[int, str]".
    • Unions created using the old syntax are no longer cached. Previously, running Union[int, str] multiple times would return the same object (Union[int, str] is Union[int, str] would be True), but now it will return two different objects. Users should use == to compare unions for equality, not is. New-style unions have never been cached this way. This change could increase memory usage for some programs that use a large number of unions created by subscripting typing.Union. However, several factors offset this cost: unions used in annotations are no longer evaluated by default in Python 3.14 because of PEP 649; an instance of :class:`types.UnionType` is itself much smaller than the object returned by Union[] was on prior Python versions; and removing the cache also saves some space. It is therefore unlikely that this change will cause a significant increase in memory usage for most users.
    • Previously, old-style unions were implemented using the private class typing._UnionGenericAlias. This class is no longer needed for the implementation, but it has been retained for backward compatibility, with removal scheduled for Python 3.17. Users should use documented introspection helpers like :func:`typing.get_origin` and :func:`typing.get_args` instead of relying on private implementation details.
    • It is now possible to use :class:`typing.Union` itself in :func:`isinstance` checks. For example, isinstance(int | str, typing.Union) will return True; previously this raised :exc:`TypeError`.
    • The __args__ attribute of :class:`typing.Union` objects is no longer writable.
    • It is no longer possible to set any attributes on :class:`typing.Union` objects. This only ever worked for dunder attributes on previous versions, was never documented to work, and was subtly broken in many cases.

    (Contributed by Jelle Zijlstra in :gh:`105499`.)

unicodedata

  • The Unicode database has been updated to Unicode 16.0.0.

unittest

urllib

  • Upgrade HTTP digest authentication algorithm for :mod:`urllib.request` by supporting SHA-256 digest authentication as specified in RFC 7616. (Contributed by Calvin Bui in :gh:`128193`.)

  • Improve ergonomics and standards compliance when parsing and emitting file: URLs.

    In :func:`urllib.request.url2pathname`:

    • Accept a complete URL when the new require_scheme argument is set to true.
    • Discard URL authority if it matches the local hostname.
    • Discard URL authority if it resolves to a local IP address when the new resolve_host argument is set to true.
    • Raise :exc:`~urllib.error.URLError` if a URL authority isn't local, except on Windows where we return a UNC path as before.

    In :func:`urllib.request.pathname2url`:

    • Return a complete URL when the new add_scheme argument is set to true.
    • Include an empty URL authority when a path begins with a slash. For example, the path /etc/hosts is converted to the URL ///etc/hosts.

    On Windows, drive letters are no longer converted to uppercase, and : characters not following a drive letter no longer cause an :exc:`OSError` exception to be raised.

    (Contributed by Barney Gale in :gh:`125866`.)

uuid

webbrowser

  • Names in the :envvar:`BROWSER` environment variable can now refer to already registered browsers for the :mod:`webbrowser` module, instead of always generating a new browser command.

    This makes it possible to set :envvar:`BROWSER` to the value of one of the supported browsers on macOS.

zipinfo

Optimizations

asyncio

base64

io

  • :mod:`io` which provides the built-in :func:`open` makes less system calls when opening regular files as well as reading whole files. Reading a small operating system cached file in full is up to 15% faster. :func:`pathlib.Path.read_bytes` has the most optimizations for reading a file's bytes in full. (Contributed by Cody Maloney and Victor Stinner in :gh:`120754` and :gh:`90102`.)

uuid

zlib

  • On Windows, zlib-ng is now used as the implementation of the :mod:`zlib` module. This should produce compatible and comparable results with better performance, though it is worth noting that zlib.Z_BEST_SPEED (1) may result in significantly less compression than the previous implementation (while also significantly reducing the time taken to compress). (Contributed by Steve Dower in :gh:`91349`.)

Deprecated

Removed

argparse

ast

asyncio

collections.abc

email

importlib

itertools

pathlib

pkgutil

pty

sqlite3

typing

urllib

Others

CPython bytecode changes

Porting to Python 3.14

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

Changes in the Python API

Build changes

PEP 761: Discontinuation of PGP signatures

PGP signatures will not be available for CPython 3.14 and onwards. Users verifying artifacts must use Sigstore verification materials for verifying CPython artifacts. This change in release process is specified in PEP 761.

C API changes

New features

Limited C API changes

Porting to Python 3.14

Deprecated

Removed