Python 3.14 新特性

编辑:

Adam Turner and Hugo van Kemenade

本文解释了 Python 3.14 相比 3.13 版本的新特性。Python 3.14 于 2025 年 10 月 7 日发布。要了解全部细节,请参阅更新日志

参见

PEP 745 – Python 3.14 发布计划

摘要 – 发布亮点

Python 3.14 是 Python 编程语言的最新稳定版本,对语言、实现和标准库进行了一系列更改。最大的变化包括模板字符串字面量延迟求值的注解,以及在标准库中支持子解释器

库方面的变更包括显著增强了 asyncio 中的内省 功能,通过新的 compression.zstd 模块支持 Zstandard,在 REPL 中实现了语法高亮,以及常规的弃用和移除,并改进了用户友好性和正确性。

本文不试图对所有新特性提供完整的规范,而是提供一个方便的概述。要了解全部细节,请参阅文档,如库参考语言参考。要理解某项变更的完整实现和设计理念,请参阅该新特性对应的 PEP;但请注意,PEP 通常在特性完全实现后便不再更新。关于从早期版本的 Python 升级的指导,请参阅移植到 Python 3.14


解释器的改进

标准库的重大改进

C API 的改进

平台支持

发布变更

新特性

PEP 649 & PEP 749: 延迟求值的注解

函数、类和模块上的注解不再被即时求值。相反,注解被存储在专用的注解函数中,并且仅在必要时才进行求值(除非使用了 from __future__ import annotations)。

这一变更旨在大多数情况下提高 Python 中注解的性能和可用性。定义注解的运行时成本被最小化,但仍然可以在运行时内省注解。如果注解包含前向引用,也不再需要将其用字符串括起来。

新的 annotationlib 模块提供了检查延迟注解的工具。注解可以按 VALUE 格式(将注解求值为运行时值,类似于早期 Python 版本的行为)、FORWARDREF 格式(用特殊标记替换未定义的名称),以及 STRING 格式(将注解作为字符串返回)进行求值。

此示例展示了这些格式的行为

>>> 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'}

移植部分包含了因这些变更可能需要进行的修改的指导,尽管在大多数情况下,代码将继续按原样工作。

(由 Jelle Zijlstra 在 PEP 749gh-119180 中贡献;PEP 649 由 Larry Hastings 编写。)

参见

PEP 649

使用描述符延迟求值注解

PEP 749

实现 PEP 649

PEP 734: 标准库中的多解释器

CPython 运行时支持在同一进程中同时运行多个 Python 副本,这一功能已经存在超过 20 年。这些独立的副本中的每一个都称为一个“解释器”。然而,该功能此前仅能通过 C-API 使用。

在 Python 3.14 中,随着新的 concurrent.interpreters 模块的引入,这一限制被移除了。

使用多解释器至少有两个显著的优点

  • 它们支持一种新的(对 Python 而言)、对人类友好的并发模型

  • 真正的多核并行

对于某些用例,软件中的并发可以提高效率并简化设计,从高层次上看是这样。但与此同时,实现和维护除了最简单的并发之外的任何东西,通常对人脑来说都是一种挑战。这尤其适用于普通的线程(例如 threading),其中所有内存都在所有线程之间共享。

通过多个隔离的解释器,你可以利用一类并发模型,如通信顺序进程(CSP)或 Actor 模型,这些模型已在其他编程语言(如 Smalltalk、Erlang、Haskell 和 Go)中取得了成功。可以将多解释器看作是线程,但具有可选的共享机制。

关于多核并行:从 Python 3.12 开始,解释器之间已经足够隔离,可以并行使用(参见 PEP 684)。这为 Python 解锁了各种受限于全局解释器锁 (GIL) 的 CPU 密集型用例。

在许多方面,使用多解释器与 multiprocessing 类似,因为它们都提供了可以并行运行且默认不共享的隔离逻辑“进程”。然而,使用多解释器时,应用程序将使用更少的系统资源,并且运行更高效(因为它停留在同一个进程内)。可以将多解释器看作是具有进程的隔离性和线程的效率。

尽管该功能已存在数十年,但由于认知度低且缺乏标准库模块,多解释器并未被广泛使用。因此,它们目前存在几个显著的局限性,预计随着该功能的主流化将得到显著改善。

当前限制

  • 每个解释器的启动尚未优化

  • 每个解释器使用的内存比必要的要多(解释器之间广泛的内部共享工作仍在继续)

  • 在解释器之间真正共享对象或其他数据的选项不多(除了 memoryview

  • PyPI 上的许多第三方扩展模块尚不兼容多解释器(所有标准库扩展模块都兼容的)

  • 目前,Python 用户对编写使用多个隔离解释器的应用程序的方法大多不熟悉

这些限制的影响将取决于未来的 CPython 改进、解释器的使用方式以及社区通过 PyPI 包解决的问题。根据具体用例,这些限制可能影响不大,所以不妨一试!

此外,未来的 CPython 版本将减少或消除开销,并提供不太适合放在 PyPI 上的实用工具。在此期间,大多数限制也可以通过扩展模块来解决,这意味着 PyPI 包可以填补 3.14 的任何空白,甚至可以回溯到 3.12,那时解释器最终被正确隔离并停止共享 GIL。同样,预计 PyPI 上会出现基于解释器的高级抽象库。

关于扩展模块,正在进行更新一些 PyPI 项目以及像 Cython、pybind11、nanobind 和 PyO3 等工具的工作。隔离扩展模块的步骤可以在隔离扩展模块中找到。隔离一个模块与支持自由线程所需的工作有很多重叠之处,因此社区在该领域正在进行的工作将有助于加速对多解释器的支持。

3.14 中还新增了:concurrent.futures.InterpreterPoolExecutor

(由 Eric Snow 在 gh-134939 中贡献。)

参见

PEP 734

PEP 750: 模板字符串字面量

模板字符串是自定义字符串处理的一种新机制。它们共享 f-string 熟悉的语法,但与 f-string 不同,它们返回一个表示字符串静态和插值部分的对象,而不是一个简单的 str

要编写一个 t-string,请使用 't' 前缀而不是 'f'

>>> variety = 'Stilton'
>>> template = t'Try some {variety} cheese!'
>>> type(template)
<class 'string.templatelib.Template'>

Template 对象提供了在字符串的静态和插值(在大括号中)部分组合之前访问它们的能力。遍历 Template 实例以按顺序访问其各个部分

>>> list(template)
['Try some ', Interpolation('Stilton', 'variety', None, ''), ' cheese!']

编写(或调用)代码来处理 Template 实例很容易。例如,这里有一个函数,它将静态部分渲染为小写,并将 Interpolation 实例渲染为大写

from string.templatelib import Interpolation

def lower_upper(template):
    """Render static parts lowercase and interpolations uppercase."""
    parts = []
    for part in template:
        if isinstance(part, Interpolation):
            parts.append(str(part.value).upper())
        else:
            parts.append(part.lower())
    return ''.join(parts)

name = 'Wenslydale'
template = t'Mister {name}'
assert lower_upper(template) == 'mister WENSLYDALE'

因为 Template 实例在运行时区分静态字符串和插值,所以它们对于清理用户输入很有用。编写一个对 HTML 中的用户输入进行转义的 html() 函数是留给读者的一个练习!模板处理代码可以提供更好的灵活性。例如,一个更高级的 html() 函数可以直接在模板中接受一个 HTML 属性的 dict

attributes = {'src': 'limburger.jpg', 'alt': 'lovely cheese'}
template = t'<img {attributes}>'
assert html(template) == '<img src="limburger.jpg" alt="lovely cheese" />'

当然,模板处理代码不需要返回一个类似字符串的结果。一个高级的 html() 可以返回一个表示类似 DOM 结构的自定义类型。

有了 t-string,开发者可以编写系统来清理 SQL、进行安全的 shell 操作、改进日志记录、处理 Web 开发中的现代思想(HTML、CSS 等),并实现轻量级的自定义业务 DSL。

(由 Jim Baker, Guido van Rossum, Paul Everitt, Koudai Aono, Lysandros Nikolaou, Dave Peck, Adam Turner, Jelle Zijlstra, Bénédikt Tran, 和 Pablo Galindo Salgado 在 gh-132661 中贡献。)

参见

PEP 750.

PEP 768: 安全的外部调试器接口

Python 3.14 引入了一个零开销的调试接口,允许调试器和性能分析器安全地附加到正在运行的 Python 进程,而无需停止或重启它们。这是对 Python 调试能力的重大增强,意味着不再需要不安全的替代方案。

新接口为附加调试器代码提供了安全的执行点,而不会修改解释器的正常执行路径或在运行时增加任何开销。因此,工具现在可以实时检查和与 Python 应用程序交互,这对于高可用性系统和生产环境来说是一项至关重要的能力。

为方便起见,此接口在 sys.remote_exec() 函数中实现。例如

import sys
from tempfile import NamedTemporaryFile

with NamedTemporaryFile(mode='w', suffix='.py', delete=False) as f:
    script_path = f.name
    f.write(f'import my_debugger; my_debugger.connect({os.getpid()})')

# Execute in process with PID 1234
print('Behold! An offering:')
sys.remote_exec(1234, script_path)

此函数允许发送 Python 代码,在目标进程的下一个安全执行点执行。然而,工具作者也可以直接实现 PEP 中描述的协议,该协议详细说明了用于安全附加到正在运行的进程的底层机制。

调试接口在设计时仔细考虑了安全性,并包括几种控制访问的机制

(由 Pablo Galindo Salgado, Matt Wozniski, and Ivona Stojanovic 在 gh-131591 中贡献。)

参见

PEP 768.

一种新型解释器

CPython 新增了一种解释器。它在实现单个 Python 操作码的小型 C 函数之间使用尾调用,而不是一个大的 C case 语句。对于某些较新的编译器,这种解释器提供了显著更好的性能。初步基准测试表明,在标准的 pyperformance 基准测试套件上,几何平均速度提高了 3-5%,具体取决于平台和架构。基准是使用 Clang 19 构建的 Python 3.14,但未使用这种新解释器。

目前,这种解释器仅适用于 Clang 19 及更新版本,在 x86-64 和 AArch64 架构上。然而,预计未来版本的 GCC 也将支持此功能。

该功能目前为可选启用。在使用新解释器时,强烈建议启用配置文件引导优化(PGO),因为这是唯一经过测试和验证能提高性能的配置。更多信息,请参阅 --with-tail-call-interp

备注

这不应与 Python 函数的尾调用优化相混淆,后者目前未在 CPython 中实现。

这种新的解释器类型是 CPython 解释器的内部实现细节。它完全不改变 Python 程序的可见行为。它可以提高它们的性能,但不改变其他任何东西。

(由 Ken Jin 在 gh-128563 中贡献,其在 CPython 中实现的思路来自 Mark Shannon, Garrett Gu, Haoran Xu, 和 Josh Haberman。)

自由线程模式的改进

CPython 的自由线程模式(PEP 703),最初在 3.13 中添加,在 Python 3.14 中得到了显著改进。PEP 703 中描述的实现已经完成,包括 C API 的更改,并且解释器中的临时变通方法被更永久的解决方案所取代。专精化自适应解释器(PEP 659)现在在自由线程模式下启用,这与许多其他优化一起极大地提高了其性能。在自由线程模式下,单线程代码的性能损失现在大约为 5-10%,具体取决于平台和 C 编译器。

从 Python 3.14 开始,在 Windows 上为自由线程构建的 CPython 编译扩展模块时,预处理器变量 Py_GIL_DISABLED 现在需要由构建后端指定,因为它将不再由 C 编译器自动确定。对于正在运行的解释器,可以使用 sysconfig.get_config_var() 找到编译时使用的设置。

新的 -X context_aware_warnings 标志控制是否启用并发安全的警告控制。对于自由线程构建,该标志默认为 true,对于启用 GIL 的构建,默认为 false。

新增了一个 thread_inherit_context 标志,如果启用,意味着用 threading.Thread 创建的线程将以 start() 调用者的 Context() 的副本启动。最重要的是,这使得由 catch_warnings 建立的警告过滤上下文被在该上下文中启动的线程(或 asyncio 任务)“继承”。它也影响其他使用上下文变量的模块,例如 decimal 上下文管理器。对于自由线程构建,该标志默认为 true,对于启用 GIL 的构建,默认为 false。

(由 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, 和许多其他人贡献。其中一些贡献者受雇于 Meta,该公司继续为支持该项目提供重要的工程资源。)

改进的错误消息

  • 当检测到 Python 关键字的拼写错误时,解释器现在会提供有用的建议。当遇到一个与 Python 关键字非常相似的单词时,解释器会在错误消息中建议正确的关键字。此功能有助于程序员快速识别和修复常见的输入错误。例如

    >>> whille True:
    ...     pass
    Traceback (most recent call last):
      File "<stdin>", line 1
        whille True:
        ^^^^^^
    SyntaxError: invalid syntax. Did you mean 'while'?
    

    虽然该功能侧重于最常见的情况,但某些拼写错误的变体可能仍会导致常规的语法错误。(由 Pablo Galindo 在 gh-132449 中贡献。)

  • 跟在 else 块后面的 elif 语句现在有了特定的错误消息。(由 Steele Farnsworth 在 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
    
  • 如果在else之后向条件表达式传递了语句,或者在if之前传递了passbreakcontinue之一,那么错误消息会高亮显示需要表达式的位置。(由 Sergey Miryanov 在 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
    
  • 当检测到未正确闭合的字符串时,错误消息会建议该字符串可能意在成为字符串的一部分。(由 Pablo Galindo 在 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?
    
  • 当字符串具有不兼容的前缀时,错误现在会显示哪些前缀是不兼容的。(由 Nikita Sobolev 在 gh-133197 中贡献。)

    >>> ub'abc'
      File "<python-input-0>", line 1
        ub'abc'
        ^^
    SyntaxError: 'u' and 'b' prefixes are incompatible
    
  • 改进了在以下情况中使用 as 与不兼容目标时的错误消息

    • 导入:import ... as ...

    • From 导入:from ... import ... as ...

    • Except 处理程序:except ... as ...

    • 模式匹配 case:case ... as ...

    (由 Nikita Sobolev 在 gh-123539gh-123562gh-123440 中贡献。)

  • 改进了尝试将不可哈希类型的实例添加到 dictset 时的错误消息。(由 CF Bolz-Tereick 和 Victor Stinner 在 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')
    
  • 改进了当支持同步上下文管理器协议的对象使用 async with 而不是 with 进入,以及异步上下文管理器协议反之亦然时的错误消息。(由 Bénédikt Tran 在 gh-128398 中贡献。)

PEP 784: 标准库中的 Zstandard 支持

新的 compression 包包含了 compression.lzmacompression.bz2compression.gzipcompression.zlib 模块,它们分别重新导出了 lzmabz2gzipzlib 模块。从 Python 3.14 开始,compression 下的新导入名称是导入这些压缩模块的首选名称。然而,现有的模块名称尚未被弃用。任何对现有压缩模块的弃用或移除,都不会早于 3.14 发布后的五年。

新的 compression.zstd 模块通过绑定 Meta 的 zstd 库,为 Zstandard 格式提供了压缩和解压 API。Zstandard 是一种被广泛采用、高效且快速的压缩格式。除了在 compression.zstd 中引入的 API 之外,还向 tarfilezipfileshutil 模块添加了对读写 Zstandard 压缩归档的支持。

这是一个使用新模块压缩一些数据的例子

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}")

可以看出,该 API 与 lzmabz2 模块的 API 类似。

(由 Emma Harper Smith, Adam Turner, Gregory P. Smith, Tomas Roun, Victor Stinner, 和 Rogdham 在 gh-132983 中贡献。)

参见

PEP 784.

Asyncio 内省功能

新增了一个命令行界面,用于检查使用异步任务的正在运行的 Python 进程,可通过 python -m asyncio ps PIDpython -m asyncio pstree PID 使用。

ps 子命令检查给定的进程 ID (PID) 并显示当前运行的 asyncio 任务的信息。它输出一个任务表:所有任务的扁平列表,包括它们的名称、协程堆栈,以及哪些任务正在等待它们。

pstree 子命令获取相同的信息,但会渲染一个可视化的异步调用树,以层级格式显示协程关系。此命令对于调试长时间运行或卡住的异步程序特别有用。它可以帮助开发者快速识别程序在哪里被阻塞,哪些任务正在等待,以及协程是如何链接在一起的。

例如,给定此代码

import asyncio

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

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

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

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

在正在运行的进程上执行新工具将产生一个如下所示的表格

python -m asyncio ps 12345

tid        task id              task name            coroutine stack                                    awaiter chain                                      awaiter name    awaiter id
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
1935500    0x7fc930c18050       Task-1               TaskGroup._aexit -> TaskGroup.__aexit__ -> main                                                                       0x0
1935500    0x7fc930c18230       Sundowning           TaskGroup._aexit -> TaskGroup.__aexit__ -> album   TaskGroup._aexit -> TaskGroup.__aexit__ -> main    Task-1          0x7fc930c18050
1935500    0x7fc93173fa50       TMBTE                TaskGroup._aexit -> TaskGroup.__aexit__ -> album   TaskGroup._aexit -> TaskGroup.__aexit__ -> main    Task-1          0x7fc930c18050
1935500    0x7fc93173fdf0       TNDNBTG              sleep -> play                                      TaskGroup._aexit -> TaskGroup.__aexit__ -> album   Sundowning      0x7fc930c18230
1935500    0x7fc930d32510       Levitate             sleep -> play                                      TaskGroup._aexit -> TaskGroup.__aexit__ -> album   Sundowning      0x7fc930c18230
1935500    0x7fc930d32890       DYWTYLM              sleep -> play                                      TaskGroup._aexit -> TaskGroup.__aexit__ -> album   TMBTE           0x7fc93173fa50
1935500    0x7fc93161ec30       Aqua Regia           sleep -> play                                      TaskGroup._aexit -> TaskGroup.__aexit__ -> album   TMBTE           0x7fc93173fa50

或一棵如下所示的树

python -m asyncio pstree 12345

└── (T) Task-1
    └──  main example.py:13
        └──  TaskGroup.__aexit__ Lib/asyncio/taskgroups.py:72
            └──  TaskGroup._aexit Lib/asyncio/taskgroups.py:121
                ├── (T) Sundowning
                   └──  album example.py:8
                       └──  TaskGroup.__aexit__ Lib/asyncio/taskgroups.py:72
                           └──  TaskGroup._aexit Lib/asyncio/taskgroups.py:121
                               ├── (T) TNDNBTG
                                  └──  play example.py:4
                                      └──  sleep Lib/asyncio/tasks.py:702
                               └── (T) Levitate
                                   └──  play example.py:4
                                       └──  sleep Lib/asyncio/tasks.py:702
                └── (T) TMBTE
                    └──  album example.py:8
                        └──  TaskGroup.__aexit__ Lib/asyncio/taskgroups.py:72
                            └──  TaskGroup._aexit Lib/asyncio/taskgroups.py:121
                                ├── (T) DYWTYLM
                                   └──  play example.py:4
                                       └──  sleep Lib/asyncio/tasks.py:702
                                └── (T) Aqua Regia
                                    └──  play example.py:4
                                        └──  sleep Lib/asyncio/tasks.py:702

如果在异步等待图中检测到循环(这可能表示编程问题),该工具会引发错误并列出阻止树构建的循环路径

python -m asyncio pstree 12345

ERROR: await-graph contains cycles - cannot print a tree!

cycle: Task-2  Task-3  Task-2

(由 Pablo Galindo, Łukasz Langa, Yury Selivanov, 和 Marta Gomez Macias 在 gh-91048 中贡献。)

并发安全的警告控制

warnings.catch_warnings 上下文管理器现在可以选择性地使用上下文变量来处理警告过滤器。通过设置 context_aware_warnings 标志来启用此功能,可以使用 -X 命令行选项或环境变量。这在将 catch_warnings 与多线程或异步任务结合使用时,提供了可预测的警告控制。对于自由线程构建,该标志默认为 true,对于启用 GIL 的构建,默认为 false。

(由 Neil Schemenauer 和 Kumar Aditya 在 gh-130010 中贡献。)

其他语言变更

  • 现在,所有 Windows 代码页在 Windows 上都作为 ‘cpXXX’ 编解码器得到支持。(由 Serhiy Storchaka 在 gh-123803 中贡献。)

  • 实现了自 C99 以来 C 标准指定的组合实数和复数的混合模式算术规则。(由 Sergey B Kirpichev 在 gh-69639 中贡献。)

  • 现在,无论优化级别和 -O 命令行选项如何,都会检测到更多的语法错误。这包括对 __debug__ 的写入、不正确使用 await,以及在异步函数之外使用异步推导式。例如,python -O -c 'assert (__debug__ := 1)'python -O -c 'assert await 1' 现在会产生 SyntaxError。(由 Irit Katriel 和 Jelle Zijlstra 在 gh-122245 & gh-121637 中贡献。)

  • 在子类化一个纯 C 类型时,如果新类型的 C 槽在子类中没有被显式覆盖,它们在类创建时将不再被替换为包装版本。(由 Tomasz Pytel 在 gh-132284 中贡献。)

内置函数

命令行和环境

  • 导入时间标志现在可以通过新的 -X importtime=2 来跟踪已加载(“缓存”)的模块。当导入这样的模块时,selfcumulative 时间将被字符串 cached 替换。

    大于 2-X importtime 值现在保留供将来使用。

    (由 Noah Kim 和 Adam Turner 在 gh-118655 中贡献。)

  • 命令行选项 -c 现在在执行前会自动对其代码参数进行反缩进。自动反缩进的行为与 textwrap.dedent() 相同。(由 Jon Crall 和 Steven Sun 在 gh-103998 中贡献。)

  • -J 不再是为 Jython 保留的标志,现在没有特殊含义。(由 Adam Turner 在 gh-133336 中贡献。)

PEP 758: 允许不带括号的 exceptexcept* 表达式

当有多个异常类型且未使用 as 子句时,exceptexcept* 表达式现在允许省略括号。例如

try:
    connect_to_server()
except TimeoutError, ConnectionRefusedError:
    print('The network has ceased to be!')

(由 Pablo Galindo 和 Brett Cannon 在 PEP 758gh-131831 中贡献。)

PEP 765: finally 代码块中的控制流

returnbreakcontinue 语句的效果是离开 finally 代码块时,编译器现在会发出一个 SyntaxWarning。这一变更在 PEP 765 中有详细说明。

在这一变更不方便的情况下(例如,由于代码检查导致警告是多余的),可以使用警告过滤器来关闭所有语法警告,方法是添加 ignore::SyntaxWarning 作为过滤器。这可以与一个将其他警告转换为错误的过滤器结合指定(例如,传递 -Werror -Wignore::SyntaxWarning 作为命令行选项,或设置 PYTHONWARNINGS=error,ignore::SyntaxWarning)。

请注意,在运行时使用 warnings 模块应用这样的过滤器,只会抑制在过滤器调整之后编译的代码中的警告。在过滤器调整之前编译的代码(例如,导入模块时)仍会发出语法警告。

(由 Irit Katriel 在 gh-130080 中贡献。)

增量式垃圾回收

循环垃圾回收器现在是增量式的。这意味着对于较大的堆,最大暂停时间减少了一个数量级或更多。

现在只有两代:年轻代和老年代。当不直接调用 gc.collect() 时,GC 的调用频率会稍微降低。当被调用时,它会收集年轻代和老年代的一个增量部分,而不是收集一个或多个完整的代。

gc.collect() 的行为略有变化

  • gc.collect(1): 执行一次增量垃圾回收,而不是收集第 1 代。

  • gc.collect() 的其他调用保持不变。

(由 Mark Shannon 在 gh-108362 中贡献。)

默认交互式终端

  • 默认的交互式终端现在会高亮显示 Python 语法。该功能默认启用,除非设置了 PYTHON_BASIC_REPL 或任何其他禁用颜色的环境变量。详情请参阅控制颜色

    语法高亮的默认颜色主题力求良好的对比度,并专门使用 4 位 VGA 标准 ANSI 颜色代码以实现最大的兼容性。可以使用实验性 API _colorize.set_theme() 自定义主题。这可以在交互式会话中或在 PYTHONSTARTUP 脚本中调用。请注意,此函数没有稳定性保证,可能会更改或被移除。

    (由 Łukasz Langa 在 gh-131507 中贡献。)

  • 默认的交互式终端现在支持导入自动补全。这意味着输入 import co 并按下 <Tab> 将会建议以 co 开头的模块。类似地,输入 from concurrent import i 将会建议 concurrent 中以 i 开头的子模块。请注意,目前不支持模块属性的自动补全。(由 Tomas Roun 在 gh-69605 中贡献。)

新增模块

  • annotationlib: 用于内省注解。更多细节请参见 PEP 749。(由 Jelle Zijlstra 在 gh-119180 中贡献。)

  • compression (包括 compression.zstd): 一个用于压缩相关模块的包,包括一个支持 Zstandard 压缩格式的新模块。更多细节请参见 PEP 784。(由 Emma Harper Smith, Adam Turner, Gregory P. Smith, Tomas Roun, Victor Stinner, 和 Rogdham 在 gh-132983 中贡献。)

  • concurrent.interpreters: 在标准库中支持多解释器。更多细节请参见 PEP 734。(由 Eric Snow 在 gh-134939 中贡献。)

  • string.templatelib: 支持模板字符串字面量(t-string)。更多细节请参见 PEP 750。(由 Jim Baker, Guido van Rossum, Paul Everitt, Koudai Aono, Lysandros Nikolaou, Dave Peck, Adam Turner, Jelle Zijlstra, Bénédikt Tran, 和 Pablo Galindo Salgado 在 gh-132661 中贡献。)

改进的模块

argparse

  • argparse.ArgumentParser程序名称的默认值现在反映了 Python 解释器被指示查找 __main__ 模块代码的方式。(由 Serhiy Storchaka 和 Alyssa Coghlan 在 gh-66436 中贡献。)

  • argparse.ArgumentParser 引入了可选的 suggest_on_error 形参,当用户输入错误时,可以为参数选项和子解析器名称提供建议。(由 Savannah Ostrowski 在 gh-124456 中贡献。)

  • 为帮助文本启用颜色,可以通过向 argparse.ArgumentParser 传入可选的 color 参数来禁用。这也可以通过环境变量来控制。(由 Hugo van Kemenade 在 gh-130645 中贡献。)

ast

  • 添加 compare(),一个用于比较两个 AST 的函数。(由 Batuhan Taskaya 和 Jeremy Hylton 在 gh-60191 中贡献。)

  • 为 AST 节点添加对 copy.replace() 的支持。(由 Bénédikt Tran 在 gh-121141 中贡献。)

  • 在优化级别 2 中,文档字符串现在会从优化的 AST 中移除。(由 Irit Katriel 在 gh-123958 中贡献。)

  • AST 节点的 repr() 输出现在包含更多信息。(由 Tomas Roun 在 gh-116022 中贡献。)

  • 当使用 AST 作为输入调用时,parse() 函数现在总是验证根节点类型是否适当。(由 Irit Katriel 在 gh-130139 中贡献。)

  • 向命令行界面添加新选项:--feature-version--optimize--show-empty。(由 Semyon Moroz 在 gh-133367 中贡献。)

asyncio

calendar

  • 默认情况下,在 calendar命令行文本输出中,今天的日期会以彩色高亮显示。这可以通过环境变量来控制。(由 Hugo van Kemenade 在 gh-128317 中贡献。)

concurrent.futures

  • 添加了一个新的执行器类 InterpreterPoolExecutor,它将同一进程中的多个 Python 解释器('子解释器')暴露给 Python 代码。它使用一个独立的 Python 解释器池来异步执行调用。

    这与 PEP 734 引入的新的 interpreters 模块是分开的。(由 Eric Snow 在 gh-124548 中贡献。)

  • 在除 macOS 之外的 Unix 平台上,‘forkserver’ 现在是 ProcessPoolExecutor 的默认启动方法 (取代了 ‘fork’)。此更改不影响 Windows 或 macOS,在这两个平台上,‘spawn’ 仍然是默认的启动方法。

    如果需要与线程不兼容的 fork 方法,你必须通过向 ProcessPoolExecutor 提供一个多进程上下文 mp_context 来显式请求它。

    有关 fork 方法的信息和差异,以及此更改可能如何影响具有可变全局共享变量和/或无法自动 pickled 的共享对象的现有代码,请参阅forkserver 限制

    (由 Gregory P. Smith 在 gh-84559 中贡献。)

  • ProcessPoolExecutor 添加了两个新方法,terminate_workers()kill_workers(),用于终止或杀死给定池中所有存活的工作进程。(由 Charles Machalow 在 gh-130849 中贡献。)

  • Executor.map 添加了可选的 buffersize 参数,以限制已提交但结果尚未产生的任务数量。如果缓冲区已满,对 iterables 的迭代将暂停,直到从缓冲区中产生一个结果。(由 Enzo Bonnal 和 Josh Rosenberg 在 gh-74028 中贡献。)

configparser

  • configparser 将不再写入它无法读取的配置文件,以提高安全性。尝试 write() 包含分隔符或以节头模式开头的键将引发一个 InvalidWriteError。(由 Jacob Lincoln 在 gh-129270 中贡献。)

contextvars

ctypes

curses

datetime

decimal

difflib

  • HtmlDiff 类生成的高亮显示更改的比较页面现在支持“暗黑模式”。(由 Jiahao Li 在 gh-129939 中贡献。)

dis

errno

faulthandler

fnmatch

  • 添加 filterfalse(),一个用于拒绝与给定模式匹配的名称的函数。(由 Bénédikt Tran 在 gh-74598 中贡献。)

fractions

functools

getopt

  • 添加对带有可选参数的选项的支持。(由 Serhiy Storchaka 在 gh-126374 中贡献。)

  • 添加支持按顺序返回混合的选项和非选项参数。(由 Serhiy Storchaka 在 gh-126390 中贡献。)

getpass

  • 通过仅关键字的可选参数 echo_chargetpass() 函数中支持键盘反馈。每当输入一个字符时,都会渲染占位符字符,删除字符时则移除。(由 Semyon Moroz 在 gh-77065 中贡献。)

graphlib

heapq

hmac

  • 使用来自 HACL* 项目的经过形式化验证的代码,为 HMAC (RFC 2104) 添加了内置实现。当 OpenSSL 的 HMAC 实现不可用时,此实现将用作后备。(由 Bénédikt Tran 在 gh-99108 中贡献。)

http

imaplib

inspect

io

json

  • 为 JSON 序列化错误添加异常注释,以帮助识别错误的来源。(由 Serhiy Storchaka 在 gh-122163 中贡献。)

  • 允许使用 -m 开关将 json 模块作为脚本使用:python -m json。现在推荐使用此方式,而不是 python -m json.tool,后者已被软弃用。请参阅 JSON 命令行界面 文档。(由 Trey Hunner 在 gh-122873 中贡献。)

  • 默认情况下,JSON 命令行界面的输出会以彩色高亮显示。这可以通过环境变量来控制。(由 Tomas Roun 在 gh-131952 中贡献。)

linecache

  • getline() 现在可以检索冻结模块的源代码。(由 Tian Gao 在 gh-131638 中贡献。)

logging.handlers

math

  • 为模块中的域错误添加了更详细的错误消息。(由 Charlie Zhao 和 Sergey B Kirpichev 在 gh-101410 中贡献。)

mimetypes

  • 为模块添加了一个公共的命令行,通过 python -m mimetypes 调用。(由 Oleg Iarygin 和 Hugo van Kemenade 在 gh-93096 中贡献。)

  • 根据 RFC 和常见用法添加了几个新的 MIME 类型

    微软和 RFC 8081 的字体 MIME 类型

    • 嵌入式 OpenType: application/vnd.ms-fontobject

    • OpenType 布局 (OTF) font/otf

    • TrueType: font/ttf

    • WOFF 1.0 font/woff

    • WOFF 2.0 font/woff2

    RFC 9559 Matroska 音视频数据容器结构的 MIME 类型

    • 无视频的音频: audio/matroska (.mka)

    • 视频: video/matroska (.mkv)

    • 立体视频: video/matroska-3d (.mk3d)

    带 RFC 的图像

    • RFC 1494: CCITT Group 3 (.g3)

    • RFC 3362: 实时传真, T.38 (.t38)

    • RFC 3745: JPEG 2000 (.jp2)、扩展 (.jpx) 和复合 (.jpm)

    • RFC 3950: 标记图像文件格式传真扩展, TIFF-FX (.tfx)

    • RFC 4047: 灵活图像传输系统 (.fits)

    • RFC 7903: 增强型图元文件 (.emf) 和 Windows 图元文件 (.wmf)

    其他 MIME 类型的新增和更改

    • RFC 2361: 将 .avi 的类型更改为 video/vnd.avi,将 .wav 的类型更改为 audio/vnd.wave

    • RFC 4337: 添加 MPEG-4 audio/mp4 (.m4a)

    • RFC 5334: 添加 Ogg 媒体 (.oga, .ogg.ogx)

    • RFC 6713: 添加 gzip application/gzip (.gz)

    • RFC 9639: 添加 FLAC audio/flac (.flac)

    • RFC 9512 YAML 文件的 application/yaml MIME 类型 (.yaml.yml)

    • 添加 7z application/x-7z-compressed (.7z)

    • 当非严格模式时,添加 Android 包 application/vnd.android.package-archive (.apk)

    • 添加 deb application/x-debian-package (.deb)

    • 添加 glTF 二进制 model/gltf-binary (.glb)

    • 添加 glTF JSON/ASCII model/gltf+json (.gltf)

    • 添加 M4V video/x-m4v (.m4v)

    • 添加 PHP application/x-httpd-php (.php)

    • 添加 RAR application/vnd.rar (.rar)

    • 添加 RPM application/x-rpm (.rpm)

    • 添加 STL model/stl (.stl)

    • 添加 Windows Media Video video/x-ms-wmv (.wmv)

    • 事实标准: 添加 WebM audio/webm (.weba)

    • ECMA-376: 添加 .docx.pptx.xlsx 类型

    • OASIS: 添加 OpenDocument .odg.odp.ods.odt 类型

    • W3C: 添加 EPUB application/epub+zip (.epub)

    (由 Sahil Prajapati 和 Hugo van Kemenade 在 gh-84852 中贡献,由 Sasha “Nelie” Chernykh 和 Hugo van Kemenade 在 gh-132056 中贡献,以及由 Hugo van Kemenade 在 gh-89416gh-85957gh-129965 中贡献。)

multiprocessing

  • 在除 macOS 之外的 Unix 平台上,‘forkserver’ 现在是默认的启动方法 (取代了 ‘fork’)。此更改不影响 Windows 或 macOS,在这两个平台上,‘spawn’ 仍然是默认的启动方法。

    如果需要与线程不兼容的 fork 方法,你必须通过 get_context() 的上下文显式请求它(推荐),或者通过 set_start_method() 更改默认值。

    有关 fork 方法的信息和差异,以及此更改可能如何影响具有可变全局共享变量和/或无法自动 pickled 的共享对象的现有代码,请参阅forkserver 限制

    (由 Gregory P. Smith 在 gh-84559 中贡献。)

  • multiprocessing'forkserver' 启动方法现在对其控制套接字进行身份验证,以避免仅仅依赖文件系统权限来限制其他进程可能导致 forkserver 派生工作进程和运行代码。(由 Gregory P. Smith 为 gh-97514 贡献。)

  • 多进程代理对象listdict 类型获得了以前被忽略的缺失方法:

    • list 代理的 clear()copy()

    • dict 代理的 fromkeys()reversed(d)d | {}{} | dd |= {'b': 2}

    (由 Roy Hyunjin Han 为 gh-103134 贡献。)

  • 通过 SyncManager.set() 添加对共享 set 对象的支持。Manager() 方法中的 set() 现在可用。(由 Mingyu Park 在 gh-129949 中贡献。)

  • multiprocessing.Process 对象添加了 interrupt() 方法,该方法通过发送 SIGINT 来终止子进程。这使得 finally 子句能够为被终止的进程打印堆栈跟踪。(由 Artem Pulkin 在 gh-131913 中贡献。)

operator

  • 添加 is_none()is_not_none() 作为一对函数,使得 operator.is_none(obj) 等价于 obj is None,而 operator.is_not_none(obj) 等价于 obj is not None。(由 Raymond Hettinger 和 Nico Mexis 在 gh-115808 中贡献。)

os

os.path

pathlib

  • pathlib.Path 添加了用于递归复制或移动文件和目录的方法:

    • copy() 将文件或目录树复制到目标位置。

    • copy_into() 复制目标目录中。

    • move() 将文件或目录树移动到目标位置。

    • move_into() 移动目标目录中。

    (由 Barney Gale 在 gh-73991 中贡献。)

  • 添加 info 属性,它存储一个实现新的 pathlib.types.PathInfo 协议的对象。该对象支持查询文件类型并在内部缓存 stat() 结果。由 iterdir() 生成的 Path 对象会用从扫描父目录中收集的文件类型信息进行初始化。(由 Barney Gale 在 gh-125413 中贡献。)

pdb

  • pdb 模块现在支持使用新的 -p PID 命令行选项远程附加到正在运行的 Python 进程:

    python -m pdb -p 1234
    

    这将连接到具有给定 PID 的 Python 进程,并允许您以交互方式对其进行调试。请注意,由于 Python 解释器的工作方式,附加到在系统调用中阻塞或等待 I/O 的远程进程,只有在执行下一个字节码指令或进程收到信号时才会起作用。

    此功能使用 PEP 768 和新的 sys.remote_exec() 函数来附加到远程进程并向其发送 PDB 命令。

    (由 Matt Wozniski 和 Pablo Galindo 在 gh-131591 中贡献。)

  • 硬编码断点 (breakpoint()set_trace()) 现在会重用调用 set_trace() 的最近一个 Pdb 实例,而不是每次都创建一个新的。因此,所有实例特定的数据,如 displaycommands,在硬编码断点之间都会被保留。(由 Tian Gao 在 gh-121450 中贡献。)

  • pdb.Pdb 添加了一个新参数 mode。当 pdb 处于 inline 模式时,禁用 restart 命令。(由 Tian Gao 在 gh-123757 中贡献。)

  • 当用户尝试在 inline 模式下退出 pdb 时,会显示一个确认提示。yY<Enter>EOF 将确认退出并调用 sys.exit(),而不是引发 bdb.BdbQuit。(由 Tian Gao 在 gh-124704 中贡献。)

  • breakpoint()pdb.set_trace() 这样的内联断点将始终在调用帧处停止程序,忽略 skip 模式(如果存在)。(由 Tian Gao 在 gh-130493 中贡献。)

  • pdb 多行输入的行首按 <tab> 现在将填充一个 4 空格的缩进,而不是插入一个 \t 字符。(由 Tian Gao 在 gh-130471 中贡献。)

  • pdb 多行输入中引入了自动缩进。它将保持上一行的缩进,或者在检测到新代码块时插入一个 4 空格的缩进。(由 Tian Gao 在 gh-133350 中贡献。)

  • 添加了 $_asynctask 以在适用时访问当前的 asyncio 任务。(由 Tian Gao 在 gh-124367 中贡献。)

  • 添加了 pdb.set_trace_async() 以支持调试 asyncio 协程。此函数支持 await 语句。(由 Tian Gao 在 gh-132576 中贡献。)

  • pdb 中显示的源代码将进行语法高亮。此功能可以使用与默认交互式 shell 相同的方法来控制,此外还新增了 pdb.Pdbcolorize 参数。(由 Tian Gao 和 Łukasz Langa 在 gh-133355 中贡献。)

pickle

  • pickle 模块上的默认协议版本设置为 5。更多详情,请参阅pickle 协议

  • 为 pickle 序列化错误添加异常注释,以帮助识别错误的来源。(由 Serhiy Storchaka 在 gh-122213 中贡献。)

platform

  • 添加 invalidate_caches(),一个用于使 platform 模块中的缓存结果无效的函数。(由 Bénédikt Tran 在 gh-122549 中贡献。)

pydoc

  • 帮助输出中的注解现在通常以更接近原始源代码的格式显示。(由 Jelle Zijlstra 在 gh-101552 中贡献。)

re

  • 正则表达式 中支持将 \z 作为 \Z 的同义词。与 \Z 不同(后者有细微的行为差异),\z 在许多其他正则表达式引擎中被明确地解释。 (由 Serhiy Storchaka 在 gh-133306 中贡献。)

  • 正则表达式 中的 \B 现在会匹配空输入字符串,这意味着它现在总是与 \b 相反。 (由 Serhiy Storchaka 在 gh-124130 中贡献。)

socket

  • 改进并修复了对蓝牙套接字的支持。

    • 修复了在 NetBSD 和 DragonFly BSD 上对蓝牙套接字的支持。 (由 Serhiy Storchaka 在 gh-132429 中贡献。)

    • 修复了在 FreeBSD 上对 BTPROTO_HCI 的支持。 (由 Victor Stinner 在 gh-111178 中贡献。)

    • 在 FreeBSD 上增加了对 BTPROTO_SCO 的支持。 (由 Serhiy Storchaka 在 gh-85302 中贡献。)

    • 在 FreeBSD 上为 BTPROTO_L2CAP 的地址增加了对 cidbdaddr_type 的支持。 (由 Serhiy Storchaka 在 gh-132429 中贡献。)

    • 在 Linux 上为 BTPROTO_HCI 的地址增加了对 channel 的支持。 (由 Serhiy Storchaka 在 gh-70145 中贡献。)

    • 在 Linux 上接受一个整数作为 BTPROTO_HCI 的地址。 (由 Serhiy Storchaka 在 gh-132099 中贡献。)

    • BTPROTO_L2CAPgetsockname() 中返回 cid。 (由 Serhiy Storchaka 在 gh-132429 中贡献。)

    • 添加了许多新常量。 (由 Serhiy Storchaka 在 gh-132734 中贡献。)

ssl

  • 通过布尔值 HAS_PHA 指示 ssl 模块是否支持 TLSv1.3 握手后客户端认证 (PHA)。 (由 Will Childs-Klein 在 gh-128036 中贡献。)

struct

  • struct 模块中支持 C 语言的 float complexdouble complex 类型(格式化字符分别为 'F''D')。 (由 Sergey B Kirpichev 在 gh-121249 中贡献。)

symtable

sys

  • 之前未写入文档的特殊函数 sys.getobjects(),仅存在于 Python 的特定构建版本中,现在可能返回来自其调用所在解释器之外的其他解释器的对象。 (由 Eric Snow 在 gh-125286 中贡献。)

  • 添加了 sys._is_immortal() 用于判断一个对象是否是 不可变 (immortal) 对象。 (由 Peter Bierma 在 gh-128509 中贡献。)

  • 在 FreeBSD 上,sys.platform 不再包含主版本号。它始终为 'freebsd',而不是 'freebsd13''freebsd14'。 (由 Michael Osipov 在 gh-129393 中贡献。)

  • sys._clear_type_cache() 引发 DeprecationWarning。该函数在 Python 3.13 中被弃用,但当时并未引发运行时警告。

  • 添加了 sys.remote_exec() 以实现新的外部调试器接口。详见 PEP 768。 (由 Pablo Galindo Salgado, Matt Wozniski 和 Ivona Stojanovic 在 gh-131591 中贡献。)

  • 添加了 sys._jit 命名空间,包含用于内省即时编译的工具。 (由 Brandt Bucher 在 gh-133231 中贡献。)

sys.monitoring

sysconfig

tarfile

threading

tkinter

  • 使得 tkinter 部件的方法 after()after_idle() 接受关键字参数。 (由 Zhikang Yan 在 gh-126899 中贡献。)

  • 增加了为 tkinter.OptionMenutkinter.ttk.OptionMenu 指定名称的功能。 (由 Zhikang Yan 在 gh-130482 中贡献。)

turtle

types

typing

  • types.UnionTypetyping.Union 类型现在互为别名,这意味着旧式联合类型(用 Union[int, str] 创建)和新式联合类型(int | str)现在都会创建相同运行时类型的实例。这统一了两种语法之间的行为,但也导致了一些行为差异,可能会影响在运行时对类型进行内省的用户。

    • 现在,创建联合类型的两种语法在 repr() 中会产生相同的字符串表示。例如,repr(Union[int, str]) 现在是 "int | str",而不是 "typing.Union[int, str]"

    • 使用旧语法创建的联合类型不再被缓存。以前,多次运行 Union[int, str] 会返回同一个对象(Union[int, str] is Union[int, str] 会是 True),但现在会返回两个不同的对象。应使用 == 来比较联合类型的相等性,而不是 is。新式联合类型从未以这种方式被缓存。对于使用大量通过对 typing.Union 进行下标操作创建的联合类型的程序,此更改可能会增加内存使用量。然而,有几个因素可以抵消这一成本:由于 PEP 649,Python 3.14 中默认不再对注解中使用的联合类型进行求值;types.UnionType 的一个实例本身比之前 Python 版本中 Union[] 返回的对象小得多;移除缓存也节省了一些空间。因此,此更改不太可能对大多数用户造成显著的内存使用增加。

    • 以前,旧式联合类型是使用私有类 typing._UnionGenericAlias 实现的。这个类现在不再需要用于实现,但为了向后兼容而保留,计划在 Python 3.17 中移除。用户应使用有文档的内省辅助函数,如 get_origin()typing.get_args(),而不是依赖于私有的实现细节。

    • 现在可以在 isinstance() 检查中使用 typing.Union 本身。例如,isinstance(int | str, typing.Union) 将返回 True;以前这会引发 TypeError

    • typing.Union 对象的 __args__ 属性不再是可写的。

    • 现在不再可以在 Union 对象上设置任何属性。这在以前的版本中仅对 dunder 属性有效,从未被文档化为有效,并且在许多情况下存在细微的错误。

    (由 Jelle Zijlstra 在 gh-105499 中贡献。)

  • TypeAliasType 现在支持星号解包。

unicodedata

  • Unicode 数据库已更新至 Unicode 16.0.0。

unittest

urllib

  • 通过支持 RFC 7616 中指定的 SHA-256 摘要认证,升级了 urllib.request 的 HTTP 摘要认证算法。 (由 Calvin Bui 在 gh-128193 中贡献。)

  • 在解析和生成 file: URL 时,改善了易用性和标准合规性。

    url2pathname()

    • 当新的 require_scheme 参数设置为 true 时,接受一个完整的 URL。

    • 如果 URL 授权方与本地主机名匹配,则丢弃 URL 授权方。

    • 当新的 resolve_host 参数设置为 true 时,如果 URL 授权方解析为本地 IP 地址,则丢弃 URL 授权方。

    • 丢弃 URL 查询和片段组件。

    • 如果 URL 授权方不是本地的,则引发 URLError,除非在 Windows 上,我们像以前一样返回一个 UNC 路径。

    pathname2url()

    • 当新的 add_scheme 参数设置为 true 时,返回一个完整的 URL。

    • 当路径以斜杠开头时,包含一个空的 URL 授权方。例如,路径 /etc/hosts 被转换为 URL ///etc/hosts

    在 Windows 上,驱动器号不再转换为大写,并且不在驱动器号后面的 : 字符不再导致引发 OSError 异常。

    (由 Barney Gale 在 gh-125866 中贡献。)

uuid

webbrowser

  • BROWSER 环境变量中的名称现在可以引用 webbrowser 模块中已注册的浏览器,而不是总是生成一个新的浏览器命令。

    这使得可以将 BROWSER 设置为 macOS 上支持的某个浏览器的值。

zipfile

优化

asyncio

  • 由于为 原生任务 实现了一个新的每线程双向链表,标准基准测试结果提高了 10-20%,同时也减少了内存使用。这使得外部内省工具(如 python -m asyncio pstree)能够内省所有线程中运行的 asyncio 任务的调用图。 (由 Kumar Aditya 在 gh-107803 中贡献。)

  • 该模块现在对 自由线程构建 (free-threading builds) 提供了一流的支持。这使得多个事件循环可以在不同线程上并行执行,并随线程数量线性扩展。 (由 Kumar Aditya 在 gh-128002 中贡献。)

base64

  • b16decode() 的速度现在快了高达六倍。 (由 Bénédikt Tran, Chris Markiewicz, 和 Adam Turner 在 gh-118761 中贡献。)

bdb

  • 基础调试器现在有了一个基于 sys.monitoring 的后端,可以通过将 'monitoring' 传递给 Bdb 类的新 backend 参数来选择。 (由 Tian Gao 在 gh-124533 中贡献。)

difflib

  • IS_LINE_JUNK() 函数的速度现在快了高达两倍。 (由 Adam Turner 和 Semyon Moroz 在 gh-130167 中贡献。)

gc

  • 新的增量垃圾回收器意味着对于较大的堆,最大暂停时间减少了一个数量级或更多。

    由于此优化,get_threshold()set_threshold() 的结果含义发生了变化,get_count()get_stats() 也是如此。

    • 为了向后兼容,get_threshold() 继续返回一个三元组。第一个值是年轻代回收的阈值,和以前一样;第二个值决定了老年代被扫描的速率(默认为 10,更高的值意味着老年代被扫描得更慢)。第三个值现在没有意义,并且总是零。

    • set_threshold() 现在会忽略第二个之后的所有项。

    • get_count()get_stats() 继续返回相同格式的结果。唯一的区别是,结果不再指代年轻代、老化代和老年代,而是指代年轻代以及老年代的老化空间和回收空间。

    总而言之,试图操纵循环垃圾回收器行为的代码可能无法完全按预期工作,但很可能不会造成危害。所有其他代码都将正常工作。

    (由 Mark Shannon 在 gh-108362 中贡献。)

io

  • 打开和读取文件现在执行的系统调用更少。完整读取一个小的操作系统缓存文件,速度提高了高达 15%。 (由 Cody Maloney 和 Victor Stinner 在 gh-120754gh-90102 中贡献。)

pathlib

  • Path.read_bytes 现在使用无缓冲模式打开文件,完整读取速度提高了 9% 到 17%。 (由 Cody Maloney 在 gh-120754 中贡献。)

pdb

uuid

  • 对于 16 字节的名称,uuid3()uuid5() 现在都快了大约 40%;对于 1024 字节的名称,快了 20%。对于更长的名称,性能保持不变。 (由 Bénédikt Tran 在 gh-128150 中贡献。)

  • uuid4() 现在快了约 30%。 (由 Bénédikt Tran 在 gh-128150 中贡献。)

zlib

  • 在 Windows 上,zlib-ng 现在被用作默认二进制文件中 zlib 模块的实现。在 zlib-ng 和之前使用的 zlib 实现之间没有已知的兼容性问题。这应该会在所有压缩级别上带来更好的性能。

    值得注意的是,zlib.Z_BEST_SPEED (1) 可能会导致比以前的实现压缩率显著降低,同时压缩时间也显著减少。

    (由 Steve Dower 在 gh-91349 中贡献。)

已移除

argparse

  • 移除了 BooleanOptionalActiontypechoicesmetavar 参数。这些参数自 Python 3.12 起已被弃用。 (由 Nikita Sobolev 在 gh-118805 中贡献。)

  • 在参数组上调用 add_argument_group() 现在会引发 ValueError。同样,在互斥组上调用 add_argument_group()add_mutually_exclusive_group() 现在都会引发 ValueError。这种“嵌套”从未被支持,经常无法正常工作,并且是通过继承无意中暴露出来的。该功能自 Python 3.11 起已被弃用。 (由 Savannah Ostrowski 在 gh-127186 中贡献。)

ast

  • 移除了以下类,它们自 Python 3.8 起是 Constant 的弃用别名,并自 Python 3.12 起发出弃用警告

    • Bytes

    • Ellipsis

    • NameConstant

    • Num

    • Str

    由于这些移除,当 NodeVisitor 子类访问 AST 时,自定义 NodeVisitor 子类上用户定义的 visit_Numvisit_Strvisit_Bytesvisit_NameConstantvisit_Ellipsis 方法将不再被调用。请改用定义 visit_Constant 方法。

    (由 Alex Waygood 在 gh-119562 中贡献。)

  • 移除了 ast.Constant 上以下已弃用的属性,这些属性是为了与现已移除的 AST 类兼容而存在的

    • Constant.n

    • Constant.s

    请改用 Constant.value。 (由 Alex Waygood 在 gh-119562 中贡献。)

asyncio

  • 移除了以下自 Python 3.12 起已被弃用的类、方法和函数

    • AbstractChildWatcher

    • FastChildWatcher

    • MultiLoopChildWatcher

    • PidfdChildWatcher

    • SafeChildWatcher

    • ThreadedChildWatcher

    • AbstractEventLoopPolicy.get_child_watcher()

    • AbstractEventLoopPolicy.set_child_watcher()

    • get_child_watcher()

    • set_child_watcher()

    (由 Kumar Aditya 在 gh-120804 中贡献。)

  • 如果没有当前的事件循环,asyncio.get_event_loop() 现在会引发 RuntimeError,并且不再隐式创建事件循环。

    (由 Kumar Aditya 在 gh-126353 中贡献。)

    有一些使用 asyncio.get_event_loop() 的模式,其中大多数可以用 asyncio.run() 替代。

    如果你正在运行一个异步函数,只需使用 asyncio.run()

    之前

    async def main():
        ...
    
    
    loop = asyncio.get_event_loop()
    try:
        loop.run_until_complete(main())
    finally:
        loop.close()
    

    之后

    async def main():
        ...
    
    asyncio.run(main())
    

    如果你需要启动某个东西,例如,一个监听套接字的服务器,然后永远运行,请使用 asyncio.run() 和一个 asyncio.Event

    之前

    def start_server(loop): ...
    
    loop = asyncio.get_event_loop()
    try:
        start_server(loop)
        loop.run_forever()
    finally:
        loop.close()
    

    之后

    def start_server(loop): ...
    
    async def main():
        start_server(asyncio.get_running_loop())
        await asyncio.Event().wait()
    
    asyncio.run(main())
    

    如果你需要在事件循环中运行某个东西,然后在它周围运行一些阻塞代码,请使用 asyncio.Runner

    之前

    async def operation_one(): ...
    def blocking_code(): ...
    async def operation_two(): ...
    
    loop = asyncio.get_event_loop()
    try:
        loop.run_until_complete(operation_one())
        blocking_code()
        loop.run_until_complete(operation_two())
    finally:
        loop.close()
    

    之后

    async def operation_one(): ...
    def blocking_code(): ...
    async def operation_two(): ...
    
    with asyncio.Runner() as runner:
        runner.run(operation_one())
        blocking_code()
        runner.run(operation_two())
    

email

  • 移除了 email.utils.localtime()isdst 参数,该参数在 Python 3.12 中被弃用并一直被忽略。 (由 Hugo van Kemenade 在 gh-118798 中贡献。)

importlib.abc

itertools

  • 移除了对 itertools 迭代器的复制、深复制和序列化操作的支持。这些操作自 Python 3.12 起已发出 DeprecationWarning。 (由 Raymond Hettinger 在 gh-101588 中贡献。)

pathlib

  • 移除了对向 Path 传递额外关键字参数的支持。在以前的版本中,任何此类参数都会被忽略。 (由 Barney Gale 在 gh-74033 中贡献。)

  • 移除了对向 PurePath.relative_to()is_relative_to() 传递额外位置参数的支持。在以前的版本中,任何此类参数都会被连接到 other 上。 (由 Barney Gale 在 gh-78707 中贡献。)

pkgutil

  • 移除了 get_loader()find_loader() 函数,这些函数自 Python 3.12 起已被弃用。 (由 Bénédikt Tran 在 gh-97850 中贡献。)

pty

  • 移除了 master_open()slave_open() 函数,这些函数自 Python 3.12 起已被弃用。请改用 pty.openpty()。 (由 Nikita Sobolev 在 gh-118824 中贡献。)

sqlite3

urllib

  • urllib.parse 中移除了 Quoter 类,该类自 Python 3.11 起已被弃用。 (由 Nikita Sobolev 在 gh-118827 中贡献。)

  • urllib.request 中移除了 URLopenerFancyURLopener 类,这些类自 Python 3.3 起已被弃用。

    myopener.open() 可以用 urlopen() 替换。myopener.retrieve() 可以用 urlretrieve() 替换。对 opener 类的自定义可以通过向 build_opener() 传递自定义处理程序来替换。 (由 Barney Gale 在 gh-84850 中贡献。)

已弃用

新的弃用项

将在 Python 3.15 中移除

  • 导入系统

    • 在模块上设置 __cached__ 但未设置 __spec__.cached 的做法已被弃用。在 Python 3.15 中,导入系统或标准库将不再设置或考虑 __cached__。(gh-97879)

    • 在模块上设置 __package__ 但未设置 __spec__.parent 的做法已被弃用。在 Python 3.15 中,导入系统或标准库将不再设置或考虑 __package__。(gh-97879)

  • ctypes:

    • 未写入文档的 ctypes.SetPointerType() 函数自 Python 3.13 起已被弃用。

  • http.server:

    • 已过时且很少使用的 CGIHTTPRequestHandler 自 Python 3.13 起已被弃用。没有直接的替代品。在将 Web 服务器与请求处理程序连接方面,任何方式 都比 CGI 更好。

    • python -m http.server 命令行接口的 --cgi 旗标自 Python 3.13 起已被弃用。

  • importlib:

    • load_module() 方法:请改用 exec_module()

  • locale:

  • pathlib:

  • platform:

    • java_ver() 自 Python 3.13 起已被弃用。此函数仅对 Jython 支持有用,其 API 令人困惑,且基本未经测试。

  • sysconfig:

  • threading:

    • RLock() 在 Python 3.15 中将不接受任何参数。传递任何参数的做法自 Python 3.14 起已被弃用,因为 Python 版本不允许任何参数,但 C 版本允许任意数量的位置或关键字参数,并忽略所有参数。

  • types:

  • typing:

    • 用于创建 NamedTuple 类的未写入文档的关键字参数语法(例如,Point = NamedTuple("Point", x=int, y=int))自 Python 3.13 起已被弃用。请改用基于类的语法或函数式语法。

    • 当使用 TypedDict 的函数式语法时,未向 fields 参数传递值 (TD = TypedDict("TD")) 或传递 None (TD = TypedDict("TD", None)) 的做法自 Python 3.13 起已被弃用。要创建一个没有字段的 TypedDict,请使用 class TD(TypedDict): passTD = TypedDict("TD", {})

    • typing.no_type_check_decorator() 装饰器函数自 Python 3.13 起已被弃用。在 typing 模块中存在八年后,它仍未被任何主流类型检查器支持。

  • wave:

  • zipimport:

将在 Python 3.16 中移除

将在 Python 3.17 中移除

  • collections.abc:

    • collections.abc.ByteString 计划在 Python 3.17 中移除。

      使用 isinstance(obj, collections.abc.Buffer) 在运行时测试 obj 是否实现了缓冲区协议。在类型注解中使用时,请使用 Buffer 或明确指定代码支持的类型的联合类型(例如,bytes | bytearray | memoryview)。

      ByteString 最初旨在作为一个抽象类,作为 bytesbytearray 的超类型。然而,由于该 ABC 从未有过任何方法,知道一个对象是 ByteString 的实例实际上并不能告诉你任何关于该对象的有用信息。其他常见的缓冲区类型,如 memoryview,也从未被理解为 ByteString 的子类型(无论是在运行时还是由静态类型检查器)。

      更多细节请参阅 PEP 688。 (由 Shantanu Jain 在 gh-91896 中贡献。)

  • typing:

    • 在 Python 3.14 之前,旧式联合类型是使用私有类 typing._UnionGenericAlias 实现的。该类不再是实现所必需的,但为了向后兼容而保留,计划在 Python 3.17 中移除。用户应使用已写入文档的内省辅助工具,如 typing.get_origin()typing.get_args(),而不是依赖于私有的实现细节。

    • typing.ByteString,自 Python 3.9 起被弃用,计划在 Python 3.17 中移除。

      使用 isinstance(obj, collections.abc.Buffer) 在运行时测试 obj 是否实现了缓冲区协议。在类型注解中使用时,请使用 Buffer 或明确指定代码支持的类型的联合类型(例如,bytes | bytearray | memoryview)。

      ByteString 最初旨在作为一个抽象类,作为 bytesbytearray 的超类型。然而,由于该 ABC 从未有过任何方法,知道一个对象是 ByteString 的实例实际上并不能告诉你任何关于该对象的有用信息。其他常见的缓冲区类型,如 memoryview,也从未被理解为 ByteString 的子类型(无论是在运行时还是由静态类型检查器)。

      更多细节请参阅 PEP 688。 (由 Shantanu Jain 在 gh-91896 中贡献。)

将在 Python 3.19 中移除

  • ctypes:

    • 在非 Windows 平台上,通过设置 _pack_ 但不设置 _layout_ 来隐式切换到与 MSVC 兼容的结构布局。

将在未来版本中移除

以下 API 将在未来被移除,但目前尚未确定移除日期。

  • argparse:

    • 嵌套参数组和嵌套互斥组的做法已被弃用。

    • add_argument_group() 传递未写入文档的关键字参数 prefix_chars 的做法现已弃用。

    • argparse.FileType 类型转换器已被弃用。

  • builtins:

    • 生成器:throw(type, exc, tb)athrow(type, exc, tb) 签名已被弃用:请改用 throw(exc)athrow(exc),即单参数签名。

    • 目前 Python 接受数字字面量紧跟关键字,例如 0in x1or x0if 1else 2。这允许了令人困惑和有歧义的表达式,如 [0x1for x in y](可以解释为 [0x1 for x in y][0x1f or x in y])。如果数字字面量紧跟关键字 andelseforifinisor,则会引发语法警告。在未来的版本中,这将改为语法错误。 (gh-87999)

    • __index__()__int__() 方法返回非 int 类型的支持:这些方法将被要求返回 int 的严格子类的实例。

    • __float__() 方法返回 float 的严格子类的支持:这些方法将被要求返回 float 的实例。

    • __complex__() 方法返回 complex 的严格子类的支持:这些方法将被要求返回 complex 的实例。

    • int() 委托给 __trunc__() 方法。

    • complex() 构造函数中将复数作为 realimag 参数传递的做法现已弃用;它应该只作为单个位置参数传递。 (由 Serhiy Storchaka 在 gh-109218 中贡献。)

  • calendar: calendar.Januarycalendar.February 常量已被弃用,并由 calendar.JANUARYcalendar.FEBRUARY 替代。 (由 Prince Roshan 在 gh-103636 中贡献。)

  • codecs: 请使用 open() 代替 codecs.open()。 (gh-133038)

  • codeobject.co_lnotab: 请改用 codeobject.co_lines() 方法。

  • datetime:

    • utcnow(): 请使用 datetime.datetime.now(tz=datetime.UTC)

    • utcfromtimestamp(): 请使用 datetime.datetime.fromtimestamp(timestamp, tz=datetime.UTC)

  • gettext: 复数值必须是整数。

  • importlib:

  • importlib.metadata:

    • EntryPoints 元组接口。

    • 返回值的隐式 None

  • logging: warn() 方法自 Python 3.3 起已被弃用,请改用 warning()

  • mailbox: 使用 StringIO 输入和文本模式的做法已被弃用,请改用 BytesIO 和二进制模式。

  • os: 在多线程进程中调用 os.register_at_fork()

  • pydoc.ErrorDuringImport: 为 exc_info 参数使用元组值的做法已被弃用,请改用异常实例。

  • re: 现在对正则表达式中的数字组引用和组名应用了更严格的规则。只有 ASCII 数字序列现在被接受为数字引用。字节模式和替换字符串中的组名现在只能包含 ASCII 字母、数字和下划线。 (由 Serhiy Storchaka 在 gh-91760 中贡献。)

  • sre_compilesre_constantssre_parse 模块。

  • shutil: rmtree()onerror 参数在 Python 3.12 中已被弃用;请改用 onexc 参数。

  • ssl 选项和协议

    • 不带协议参数的 ssl.SSLContext 已被弃用。

    • ssl.SSLContext: set_npn_protocols()selected_npn_protocol() 已被弃用:请改用 ALPN。

    • ssl.OP_NO_SSL* 选项

    • ssl.OP_NO_TLS* 选项

    • ssl.PROTOCOL_SSLv3

    • ssl.PROTOCOL_TLS

    • ssl.PROTOCOL_TLSv1

    • ssl.PROTOCOL_TLSv1_1

    • ssl.PROTOCOL_TLSv1_2

    • ssl.TLSVersion.SSLv3

    • ssl.TLSVersion.TLSv1

    • ssl.TLSVersion.TLSv1_1

  • threading 方法

  • typing.Text (gh-92332)。

  • 内部类 typing._UnionGenericAlias 不再用于实现 typing.Union。为了保持与使用此私有类的用户的兼容性,将提供一个兼容性垫片,直到至少 Python 3.17。 (由 Jelle Zijlstra 在 gh-105499 中贡献。)

  • unittest.IsolatedAsyncioTestCase: 从测试用例返回非 None 的值的做法已被弃用。

  • urllib.parse 已弃用的函数:请改用 urlparse()

    • splitattr()

    • splithost()

    • splitnport()

    • splitpasswd()

    • splitport()

    • splitquery()

    • splittag()

    • splittype()

    • splituser()

    • splitvalue()

    • to_bytes()

  • wsgiref: SimpleHandler.stdout.write() 不应进行部分写入。

  • xml.etree.ElementTree: 测试 Element 的真值已被弃用。在未来的版本中,它将始终返回 True。请优先使用显式的 len(elem)elem is not None 测试。

  • sys._clear_type_cache() 已被弃用:请改用 sys._clear_internal_caches()

CPython 字节码变更

伪指令

  • 添加 ANNOTATIONS_PLACEHOLDER 伪指令,以支持通过延迟求值注解来处理部分执行的模块级注解。 (由 Jelle Zijlstra 在 gh-130907 中贡献。)

  • 添加 BINARY_OP_EXTEND 伪指令,它执行从内联缓存中访问的一对函数(保护函数和特化函数)。 (由 Irit Katriel 在 gh-100239 中贡献。)

  • CALL_KW 添加三个特化版本;CALL_KW_PY 用于调用 Python 函数,CALL_KW_BOUND_METHOD 用于调用绑定方法,CALL_KW_NON_PY 用于所有其他调用。 (由 Mark Shannon 在 gh-118093 中贡献。)

  • 添加 JUMP_IF_TRUEJUMP_IF_FALSE 伪指令,它们是不影响栈的条件跳转。被 COPY 1TO_BOOLPOP_JUMP_IF_TRUE/FALSE 序列所取代。 (由 Irit Katriel 在 gh-124285 中贡献。)

  • 添加 LOAD_CONST_MORTAL 伪指令。 (由 Mark Shannon 在 gh-128685 中贡献。)

  • 添加 LOAD_CONST_IMMORTAL 伪指令,其功能与 LOAD_CONST 相同,但对于不朽对象更高效。 (由 Mark Shannon 在 gh-125837 中贡献。)

  • 添加 NOT_TAKEN 伪指令,由 sys.monitoring 用于记录分支事件(如 BRANCH_LEFT)。 (由 Mark Shannon 在 gh-122548 中贡献。)

C API 变更

Python 配置 C API

添加一个 PyInitConfig C API,用于配置 Python 初始化,而不依赖于 C 结构体,并能够在未来进行 ABI 兼容的更改。

通过添加 PyInitConfig_AddModule() 来完善 PEP 587PyConfig C API,该函数可用于添加内置扩展模块;这个功能之前被称为“inittab”。

添加 PyConfig_Get()PyConfig_Set() 函数,以获取和设置当前运行时配置。

PEP 587 “Python 初始化配置”统一了所有配置 Python 初始化的方式。此 PEP 还将 Python 的预初始化和初始化的配置统一到单个 API 中。此外,此 PEP 只为嵌入 Python 提供了一个单一的选择,而不是像(PEP 587)那样提供“Python”和“Isolated”两个选择,从而进一步简化了 API。

对于需要与 CPython 实现细节有更高耦合度的用例(例如模拟 CPython CLI 的全部功能,包括其配置机制),较低级别的 PEP 587 PyConfig API 仍然可用。

(由 Victor Stinner 在 gh-107954 中贡献。)

参见

PEP 741PEP 587

C API 中的新功能

受限 C API 变更

已移除的 C API

  • 在 Python 3.12 中,使用可变基类创建 不可变类型 已被弃用,现在会引发 TypeError。(由 Nikita Sobolev 在 gh-119775 中贡献。)

  • 移除在 Python 3.12 中已弃用的 PyDictObject.ma_version_tag 成员。请改用 PyDict_AddWatcher() API。(由 Sam Gross 在 gh-124296 中贡献。)

  • 移除私有函数 _Py_InitializeMain()。这是 PEP 587 在 Python 3.8 中添加的一个临时 API。(由 Victor Stinner 在 gh-129033 中贡献。)

  • 移除未在文档中载明的 API Py_C_RECURSION_LIMITPyThreadState.c_recursion_remaining。它们是在 3.13 中添加的,现已被移除而未经过弃用流程。请使用 Py_EnterRecursiveCall() 来防止 C 代码中出现失控递归。(由 Petr Viktorin 在 gh-133079 中移除,另请参阅 gh-130396。)

已弃用的 C API

将在 Python 3.15 中移除

将在 Python 3.16 中移除

  • 捆绑的 libmpdec 副本。

将在 Python 3.18 中移除

将在未来版本中移除

以下 API 已被弃用,并将在未来被移除,但目前尚未确定移除日期。

构建方面的变化

  • PEP 776:Emscripten 现在是第 3 级的官方支持平台。作为这项工作的一部分,修复了 Emscripten libc 中的 25 个以上错误。Emscripten 现在支持 ctypestermiosfcntl,并对新的默认交互式 Shell 提供了实验性支持。(由 R. Hood Chatham 在 gh-127146gh-127683gh-136931 中贡献。)

  • 现在 python.org 上提供了官方的 Android 二进制发行版。

  • 现在需要 GNU Autoconf 2.72 来生成 configure。(由 Erlend Aasland 在 gh-115765 中贡献。)

  • wasm32-unknown-emscripten 现在是PEP 11 的第 3 级平台。(由 R. Hood Chatham 在 gh-127146gh-127683gh-136931 中贡献。)

  • 现在可以通过 Py_NO_LINK_LIB 关闭基于 #pragma 的与 python3*.lib 的链接。(由 Jean-Christophe Fillion-Robin 在 gh-82909 中贡献。)

  • CPython 现在默认启用一组推荐的编译器选项以提高安全性。使用 --disable-safety configure 选项可禁用它们,或使用 --enable-slower-safety 选项以启用更大范围的编译器选项,但这会带来性能开销。

  • WITH_FREELISTS 宏和 --without-freelists configure 选项已被移除。

  • 新的 configure 选项 --with-tail-call-interp 可用于启用实验性的尾调用解释器。更多细节请参阅一种新型解释器

  • 要禁用新的远程调试支持,请使用 --without-remote-debug configure 选项。出于安全原因,这可能很有用。

  • iOS 和 macOS 应用程序现在可以配置为将 stdoutstderr 的内容重定向到系统日志。(由 Russell Keith-Magee 在 gh-127592 中贡献。)

  • iOS 测试平台现在能够在测试运行时流式传输测试输出。该测试平台还可用于运行 CPython 以外的项目的测试套件。(由 Russell Keith-Magee 在 gh-127592 中贡献。)

build-details.json

Python 的安装现在包含一个新文件 build-details.json。这是一个静态 JSON 文档,包含 CPython 的构建细节,以便在无需运行代码的情况下进行内省。这对于 Python 启动器、交叉编译等用例很有帮助。

build-details.json 必须安装在平台无关的标准库目录中。这对应于 ‘stdlib’ sysconfig 安装路径,可通过运行 sysconfig.get_path('stdlib') 找到。

参见

PEP 739build-details.json 1.0 – 一个描述 Python 构建细节的静态文件

停止使用 PGP 签名

Python 3.14 或未来版本的发布将不再提供 PGP (Pretty Good Privacy) 签名。要验证 CPython 的构建产物,用户必须使用 Sigstore 验证材料。自 Python 3.11 起,发布版本已开始使用 Sigstore 进行签名。

发布流程的这一变化在 PEP 761 中有详细说明。

自由线程 Python 获官方支持

Python 的自由线程构建版本现在已获得支持,不再是实验性的。这是 第二阶段 的开始,自由线程 Python 获得官方支持,但仍然是可选的。

自由线程团队相信该项目正走在正确的道路上,并感谢所有为使自由线程在 Python 社区中得到更广泛应用而持续奉献的人们。

随着这些建议和此 PEP 的接受,Python 开发者社区应广泛宣传自由线程现在和将来都是一个受支持的 Python 构建选项,并且在没有适当的弃用时间表的情况下不会被移除。

任何关于进入 第三阶段,将自由线程作为 Python 的默认或唯一构建版本的决定都尚未确定,这取决于 CPython 内部和社区的许多因素。这个决定留待未来。

实验性即时编译器的二进制发行版

官方的 macOS 和 Windows 二进制发行版现在包含一个*实验性*的即时 (JIT) 编译器。虽然它**不**推荐用于生产环境,但可以通过设置环境变量 PYTHON_JIT=1 来进行测试。下游的源码构建和再分发者可以使用 --enable-experimental-jit=yes-off 配置选项以获得类似的行为。

JIT 仍处于早期阶段,并在积极开发中。因此,启用它对性能的典型影响范围从慢 10% 到快 20% 不等,具体取决于工作负载。为了帮助测试和评估,sys._jit 命名空间中提供了一组内省函数。sys._jit.is_available() 可用于确定当前可执行文件是否支持 JIT 编译,而 sys._jit.is_enabled() 可用于判断当前进程是否已启用 JIT 编译。

目前,最主要的功能缺失是,像 gdbperf 这样的原生调试器和性能分析器无法通过 JIT 帧进行堆栈回溯(Python 调试器和性能分析器,如 pdbprofile,则可以继续正常工作)。自由线程构建版本不支持 JIT 编译。

如果您遇到任何错误或重大的性能回归,请报告!

参见

PEP 744

移植到 Python 3.14

本节列出了前面描述过的变更以及其他可能需要修改代码的 bug 修复。

Python API 的变化

  • 在除 macOS 以外的 Unix 平台上,forkserver 现在是 multiprocessingProcessPoolExecutor 的默认启动方法,取代了 fork

    详情请见 (1)(2)

    如果您遇到来自 multiprocessingconcurrent.futuresNameError 或 pickling 错误,请参阅forkserver 限制

    此更改不影响 Windows 或 macOS,在这两个平台上 ‘spawn’ 仍然是默认的启动方法。

  • functools.partial 现在是一个方法描述符。如果您想保留旧的行为,请用 staticmethod() 包装它。(由 Serhiy Storchaka 和 Dominykas Grigonis 在 gh-121027 中贡献。)

  • 垃圾回收器现在是增量式的,这意味着 gc.collect() 的行为略有变化

    • gc.collect(1): 执行一次增量垃圾回收,而不是收集第 1 代。

    • gc.collect() 的其他调用保持不变。

  • locale.nl_langinfo() 函数现在在某些情况下会临时设置 LC_CTYPE locale。这种临时更改会影响其他线程。(由 Serhiy Storchaka 在 gh-69998 中贡献。)

  • types.UnionType 现在是 typing.Union 的别名,导致某些行为发生变化。更多细节请参阅上文。(由 Jelle Zijlstra 在 gh-105499 中贡献。)

  • 注解的运行时行为在多个方面发生了变化;详情请见上文。虽然大多数与注解交互的代码应能继续工作,但一些未在文档中载明的细节可能会有不同的表现。

  • 作为将 mimetypes CLI 公开的一部分,它现在在失败时以 1 退出,而不是 0,在命令行参数不正确时以 2 退出,而不是 1。错误消息现在会打印到 stderr。

  • 正则表达式中的 \B 模式现在在作为整个模式给出时匹配空字符串,这可能会导致行为变化。

  • 在 FreeBSD 上,sys.platform 不再包含主版本号。

注解的变化 (PEP 649PEP 749)

本节提供了关于注解或与注解交互或内省的 Python 代码可能需要进行的更改的指导,这些更改是由于注解的延迟求值相关的变化所致。

在大多数情况下,旧版本 Python 中的有效代码不需要任何更改。

对带注解代码的影响

如果您在代码中定义了注解(例如,用于静态类型检查器),那么此更改可能不会影响您:您可以像在以前版本的 Python 中一样继续编写注解。

您很可能可以移除注解中的带引号字符串,这些字符串通常用于前向引用。类似地,如果您使用 from __future__ import annotations 来避免在注解中编写字符串,那么一旦您只支持 Python 3.14 及更高版本,您很可能可以移除该导入。但是,如果您依赖于读取注解的第三方库,这些库可能需要进行更改以支持不带引号的注解,才能按预期工作。

__annotations__ 读取者的影响

如果您的代码读取对象上的 __annotations__ 属性,您可能需要进行更改以支持依赖于注解延迟求值的代码。例如,您可能希望使用带 FORWARDREF 格式的 annotationlib.get_annotations(),就像 dataclasses 模块现在所做的那样。

外部 typing_extensions 包提供了对 annotationlib 模块部分功能的向后移植,例如 Format 枚举和 get_annotations() 函数。这些可以用于编写利用 Python 3.14 中新行为的跨版本代码。

from __future__ import annotations

在 Python 3.7 中,PEP 563 引入了 from __future__ import annotations future 语句,它将所有注解都转换为字符串。

但是,此语句现已弃用,并预计将在未来的 Python 版本中移除。此移除将不会在 Python 3.13(最后一个不支持注解延迟求值的 Python 版本)于 2029 年结束生命周期之后发生。

在 Python 3.14 中,使用 from __future__ import annotations 的代码的行为保持不变。

C API 的变化

  • Py_Finalize() 现在会删除所有驻留字符串。这对于任何在调用 Py_Finalize() 后仍持有驻留字符串,并在调用 Py_Initialize() 后重新使用的 C 扩展都是向后不兼容的。由此行为引起的任何问题通常会导致在后续调用 Py_Initialize() 时因访问未初始化的内存而崩溃。要修复此问题,请使用地址消毒剂来识别任何来自驻留字符串的释放后使用,并在模块关闭期间释放它。(由 Eddie Elizondo 在 gh-113601 中贡献。)

  • 如果Unicode 异常对象 C API 的异常参数不是 UnicodeError 对象,它现在会引发 TypeError。(由 Bénédikt Tran 在 gh-127691 中贡献。)