Skip to content

Latest commit

 

History

History
2075 lines (1504 loc) · 75.6 KB

3.14.rst

File metadata and controls

2075 lines (1504 loc) · 75.6 KB

What's new in Python 3.14

Editor:TBD

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

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.14 moves towards release, so it's worth checking back even after reading earlier versions.

Summary -- release highlights

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>`.

New features

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.

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.

See PEP 768 for more details.

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

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`.)

PEP 649: 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. 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 usually 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. 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.

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.

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.

Improved error messages

  • 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)
  • 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?

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`.

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.)

Other language changes

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 R 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`.)

bdb

calendar

concurrent.futures

contextvars

ctypes

datetime

decimal

difflib

dis

errno

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`.)

graphlib

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

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 9639: Add FLAC audio/flac (.flac)
    • 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`.)

multiprocessing

operator

os

pathlib

pdb

pickle

platform

pydoc

ssl

struct

symtable

sys

sys.monitoring

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 authorities that resolve to a local IP address.
    • Raise :exc:`~urllib.error.URLError` if a URL authority doesn't resolve to a local IP address, except on Windows where we return a UNC path.

    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

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