Python 3.15 有什么新变化

编者:

Hugo van Kemenade

本文介绍了 Python 3.15 相比 3.14 的新增特性。

详情请参阅 更新日志。

备注

预发布版用户应当了解到此文档目前处于草稿状态。 它将随着 Python 3.15 的发布进程不断更新,因此即使已经阅读过较早的版本也仍然值得再次查看。

摘要 -- 发布重点

Python 3.15 将是 Python 编程语言的最新稳定发布版,包含多项针对语言、实现和标准库的改变。 最大的变化包括 惰性导入, 冻结字典 和 哨兵 内置类型, UTF-8 作为默认编码格式, 推导式内解包,以及 针对自由线程构建版的稳定 ABI。

标准库的变化包括新的 性能分析软件包,其中有高频统计采样性能分析器 Tachyon,命令行输出具有 更丰富色彩,还有常规的弃用和移除,以及用户友好度和正确性方面的改进。

本文并不试图提供所有新特性的完整规范说明,而是给出一个方便的概览。 要了解完整细节请参阅相应文档,如 库参考 和 语言参考。 要了解某项改变的完整实现和设计理念,请参阅相应新特性的 PEP;但请注意一旦某项特性已完全实现则其 PEP 通常不会再保持更新。

请参阅 Porting to Python 3.15 了解关于从较早的 Python 版本进行升级的指导。


解释器的改进:

标准库中的重大改进:

新的类型标注特性:

C API 的改进:

构建的改变:

发布包的变更:

新的特性

PEP 810: 显式惰性导入

大型 Python 应用程序经常会有启动时间缓慢的困扰 。此问题有很大一部分是来自导入系统:当一个模块被导入时,Python 必须定位文件,将其从磁盘读入,将其编译为字节码,并执行全部的最高层级代码。 对于具有较深依赖树的应用程序来说,此过程耗时将以秒计,即使在大部分被导入代码在某次运行期间从未被实际使用时也是如此。

开发者要绕过此问题可通过将导入移至函数内部,使用 importlib 按需加载模块,或重新调整代码结构以避免不需要的依赖项。 这些方式有一定效果但会使代码变得更难阅读和维护,使代码库中的 import 语句到处零星散布,并需要严格制定规则才能持续应用。

Python 现在会使用新的 lazy 软关键字通过显式的 lazy 导入提供一种更清晰的解决方案。Python 将延迟实际的模块加载直到所导入的名称首次被使用。 这在组织方面给予你在文件顶部声明所有导入的便利同时只付出你实际使用模块的加载耗时。

lazy 关键字同时适用于 import 和 from ... import 语句。 当你使用 lazy import heavy_module 的写法时,Python 不会立即加载该模块。 作为替代,它将创建一个轻量的代理对象。 实际的模块加载会在你首次访问该名称时透明地发生:

lazy import json
lazy from pathlib import Path

print("Starting up...")  # json 和 pathlib 尚未加载

data = json.loads('{"key": "value"}')  # json 在这里加载
p = Path(".")  # pathlib 在这里加载

这种机制特别适用于在最高层级导入大批模块但在任何给定运行中仅使用它们的一个子集的应用程序。 延迟加载可减少启动反应时间而无需代码重新调整结构或在代码库中零散使用有条件的导入。

对于加载惰性导入模块失败的情况(例如,当模块不存在时),Python 会在首次使用时而不是导入时引发异常。 相关的回溯将同时包括名称被访问的位置和初始的 import 语句,以使对失败的诊断和调试更为直观。

对于在你希望全局启用惰性加载而不必修改源代码的场景,Python 提供了 -X lazy_imports 命令行选项和 PYTHON_LAZY_IMPORTS 环境变量。 两者均接受两种值: all 使所有导入默认为惰性的,而 normal (缺省值) 将遵循源代码中的 lazy 关键字。 sys.set_lazy_imports() 和 sys.get_lazy_imports() 函数现在允许在运行时修改和查询此模式。

想要更有选择性的控制,sys.set_lazy_imports_filter() 接受一个可调用对象决定是否应惰性加载特定的模块。 该过滤器接收三个参数:要导入模块的名称 (或 None),已导入模块的名称,以及 fromlist (或 None 表示用于常规导入)。它应返回 True 表示允许惰性导入,或 False 表示以强制立即加载。 这将允许只让你自己的应用的模块采用惰性导入而而让第三方依赖项采用立即导入的模式:

import sys

def myapp_filter(importing, imported, fromlist):
    return imported.startswith("myapp.")
sys.set_lazy_imports_filter(myapp_filter)
sys.set_lazy_imports("all")

import myapp.slow_module  # 惰性(匹配过滤器)
import json               # 立即(不匹配过滤器)

对于需要以编程方式检测惰性导入的代码来说代理类型本身可通过 types.LazyImportType 访问。

在哪里可以使用 lazy 关键字是有一些限制的。 惰性导入仅在模块作用域上被允许;在函数、类语句体或 try/except/finally 语句块中使用 lazy 会引发 SyntaxError。 星号导入和 future 导入都不能是惰性的 (lazy from module import * 和 lazy from __future__ import ... 都会引发 SyntaxError)。

对于无法直接使用 lazy 关键字的代码(例如,在要支持早于 3.15 的 Python 版本而仍使用 3.15+ 的惰性导入时),一个模块可以定义 __lazy_modules__ 作为完整限定名称字符串的容器。 用于这些模块的常规 import 语句就会被视为惰性的,具有与 lazy 关键字一样的语义:

__lazy_modules__ = ["json", "pathlib"]

import json     # 惰性
import os       # 仍为立即型

(由 Pablo Galindo Salgado 和 Dino Viehland 在 gh-142349 中贡献。)

参见

完整规范说明及考量见 PEP 810。

PEP 814: 增加 frozendict 内置类型

在 builtins 模块中增加了一个新的 immutable 类型 frozendict。 它在创建之后就不允许修改。 frozendict 不是 dict 的子类;它直接继承自 object。 一个 frozendict 在它的键与值都是可哈希对象的情况下就将是 hashable 对象。 frozendict 会保持其插入顺序,但在比较时不会将顺序纳入考虑。

例如:

>>> a = frozendict(x=1, y=2)
>>> a
frozendict({'x': 1, 'y': 2})
>>> a['z'] = 3
Traceback (most recent call last):
  File "<python-input-2>", line 1, in <module>
    a['z'] = 3
    ~^^^^^
TypeError: 'frozendict' object does not support item assignment
>>> b = frozendict(y=2, x=1)
>>> hash(a) == hash(b)
True
>>> a == b
True

下述标准库模块已对应更新到接受 frozendict: copy,decimal,json,marshal,plistlib (仅在序列化时),pickle,pprint 和 xml.etree.ElementTree。

eval() 和 exec() 接受 frozendict 作为 globals,而 type() 和 str.maketrans() 接受 frozendict 作为 dict。

通过 isinstance(arg, dict) 检测 dict 类型的代码可以更新为 isinstance(arg, (dict, frozendict)) 以同时接受 frozendict,或更新为 isinstance(arg, collections.abc.Mapping) 以接受包括 MappingProxyType 在内的其他映射类型。

(由 Victor Stinner 和 Donghee Na 在 gh-141510 中贡献。)

参见

完整规范说明及考量见 PEP 814。

PEP 661: 增加 sentinel 内置类型

在 builtins 模块中新增 sentinel 类型用于创建带有精确表示的哨兵值。 哨兵对象在拷贝时会保留其标识号,支持在类型表达式中的 | 运算符,并在它们按模块和名称导入时可以被封存。

(由 Jelle Zijlstra 在 gh-148829 中贡献。;PEP 661 由 Tal Einat 撰写。)

参见

更多细节参见 PEP 661。

PEP 799: 专用的性能分析包

新增的 profiling 模块将 Python 的内置性能分析工具整合到单独的、统一的命名空间中。 该模块包含:

cProfile 模块仍作为一个别名保留用于向下兼容。 profile 模块已被弃用并将在 Python 3.17 中移除。

(由 Pablo Galindo 和 László Kiss Kollár 在 gh-138122 中贡献。)

参见

详情见 PEP 799。

Tachyon: 高频统计型采样性能分析器

Tachyon 性能分析器标志

新增一个采样型性能分析器 (Tachyon) 并以 profiling.sampling 作为模块。 此性能分析器将为运行中的 Python 进行启用低开销的性能分析而无需代码修改或进程重启。

不同于测量每次函数调用的确定型性能分析器 (如 profiling.tracing),采样型性能分析器会定期捕获来自运行中进程的栈追踪信息。 此方式可在实际零开销的情况下获得 最高 1,000,000 Hz 的采样率,使其成为 Python 中目前(在其发布时)最快的采样型性能分析器并适用于解决生产环境下的调试性能问题。 这种能力对于传统性能分析方式侵入性过高的生产系统的调试性能问题是理想的解决方案。

关键特性包括:

  • 零开销性能分析: 附加到任何运行中的 Python 进程而不影响其性能。 对于不便重启或减慢的应用程序的生产环境调试来说非常理想。

  • 无需代码修改: 对现有应用程序进行性能分析不必重启。 只需简单地将性能分析器按 PID 指向运行中的进程并开始收集数据。

  • 灵活的目标模式:

    • 按 PID 对运行中的进程进行性能分析 (attach) - 附加到已运行的应用程序

    • 直接运行脚本并进行性能分析 (run) - 从最初执行位置开始性能分析

    • 执行模块并进行性能分析 (run -m) - 通过运行 python -m module 对包进行性能分析

    • 抓取运行中的进程的一次性快照 (dump) - 打印每个线程的回溯风格栈信息(或使用 --async-aware 则为所有的 asyncio 任务)。 适用于调查挂起的进程。

  • 多重性能分析模式: 基于你的性能调查选择衡量指标:

    • 挂钟时间 (--mode wall, 缺省值): 衡量真实花费时间包括 I/O, 网络等待和阻塞型操作。 使用此模式了解你的程序的实际耗时花费在哪里,包括对外部资源的等待。

    • CPU 时间 (--mode cpu): 仅衡量激活的 CPU 执行时间,不包括 I/O 等待和阻塞。 使用此模式来确定 CPU 密集型瓶颈并优化计算工作。

    • GIL 持有时间 (--mode gil): 衡量在持有 Python 的全局解释器锁的情况下花费的时间。 使用此模式来确定在多线程应用程序中哪个线程主导了 GIL 的使用。

    • 异常处理时间 (--mode exception): 仅捕获来自有激活异常的线程的采样。 使用此模式来分析异常处理的开销。

  • 线程感知性能分析: 选择对所有线程 (-a) 或是只对主线程进行性能分析,在分析多线程应用程序行为时非常关键。

  • 多种输出格式: 选择最适合你的工作流程的可视化:

    • --pstats: 与 pstats 兼容的详细表格型统计。 显示包含直接和累积采样的函数级耗时。 适用于详细分析以及与现有 Python 性能分析工具的集成。

    • --collapsed: 生成展开的栈追踪信息(每个栈一行)。 此格式专门设计用于通过外部工具如 Brendan Gregg 的 FlameGraph 脚本或 speedscope 来创建火焰图。

    • --flamegraph: 使用 D3.js 生成自包含的交互式 HTML 火焰图。 直接在你的浏览器中打开进行即时可视化分析。 火焰图将显示调用层级结构其中宽度代表耗费的时间,可以很容易地一眼找出性能瓶颈。

    • --gecko: 生成与 Firefox Profiler 兼容的 Gecko Profiler 格式。 将输出上传到 Firefox Profiler 用于基于时间线的分析包括栈图表、标记和网络活动等高级特性。

    • --heatmap: 生成带有行级采样计数的交互式 HTML heatmap 可视化形式。 创建一个目录包含显示源代码层级时间耗费位置的每个 heatmap 文件。

  • 实时交互模式: 具有与 top 类似界面的实时 TUI 性能分析器 (--live)。 使你的应用程序在带有交互式排序和过滤的情况下运行并监视执行效率。

  • 异步感知性能分析: 使用基于任务的栈重建对 async/await 代码进行性能分析 (--async-aware)。 查看哪些协程最为耗时,并可选择只显示运行中的任务或全部任务包括等待中的任务。

  • 操作码级性能分析: 收集字节码的操作码信息用于在指令层级进行性能分析 (--opcodes)。 显示哪些字节码指令正在执行,包括来自适配解释器的专门化。

请参阅 profiling.sampling 获取完整文档,包括所有可用的输出格式、性能分析模式以及配置选项。

(由 Pablo Galindo 和 László Kiss Kollár 在 gh-135953 和 gh-138122 中贡献。).)

PEP 831: 默认启用帧指针

现在 CPython 会在受支持的平台上默认附带帧指针进行构建。 这将使用编译器旗标 -fno-omit-frame-pointer 和 -mno-omit-leaf-frame-pointer,使得原生栈展开更快速且对系统性能分析器、调试器、崩溃分析工具和基于 eBPF 观察能力工具来说更可靠。

这些旗标是通过 sysconfig 对外暴露的,因此由使用 Python 构建配置的工具所构建的扩展模块默认会继承帧指针。 这样的传播是有意设计的:混合 Python 与原生性能分析需要一个跨解释器、扩展模块、嵌入应用程序以及原生库的连续帧指针链。

重要

第三方构建后端和原生构建系统应当在它们使用 Pytho 的 sysconfig 值时保留这些旗标。 编译 C, C++, Rust 或其他原生代码而不继承 Python 的编译器旗标的构建系统应当自行启用等价的帧指针旗标。 只要有一个构建时不带帧指针的原生组件就可能破坏整个 Python 进程的栈展开。

(由 Pablo Galindo Salgado 和 Savannah Ostrowski 在 gh-149201 中贡献;PEP 831 由 Pablo Galindo Salgado, Ken Jin, Savannah Ostrowski 和 Diego Russo 撰写。)

参见

更多细节参见 PEP 831。

PEP 798: 推导式中的解包

列表、集合与字典推导式,以及生成器表达式现在都支持使用 * 和 ** 进行解包。 这将 PEP 448 的解包语法扩展到推导式,提供了将任意多个可迭代对象或字典合并至一个展平的结构的新语法。 这种新语法是嵌套推导式, itertools.chain() 和 itertools.chain.from_iterable() 等的直接替代物。 例如:

>>> lists = [[1, 2], [3, 4], [5]]
>>> [*L for L in lists]  # 等价于 [x for L in lists for x in L]
[1, 2, 3, 4, 5]

>>> sets = [{1, 2}, {2, 3}, {3, 4}]
>>> {*s for s in sets}  # 等价于 {x for s in sets for x in s}
{1, 2, 3, 4}

>>> dicts = [{'a': 1}, {'b': 2}, {'a': 3}]
>>> {**d for d in dicts}  # 等价于 {k: v for d in dicts for k,v in d.items()}
{'a': 3, 'b': 2}

生成器表达式可以类似地进行解包从多个可迭代对象产生值:

>>> gen = (*L for L in lists)  # 等价于 (x for L in lists for x in L)
>>> list(gen)
[1, 2, 3, 4, 5]

这项改变也将扩展至异步生成器表达式,举例来说,它使得 (*a async for a in agen()) 等价于 (x async for a in agen() for x in a)。

(由 Adam Hartz 在 gh-143055 中贡献。)

参见

详情见 PEP 798。

PEP 829: 包启动配置文件

当未给出 -S 时将由 site 模块加载,.pth 文件 可包含同时扩展 sys.path 和以 import 打头(跟一个空格或制表符)时执行任意代码的行。 后者的功能可能存在问题,因为难以确定在 Python 启动时会执行什么。

作为提升对预启动可执行代码审计能力的一个步骤,Python 3.15 引入了包含 pkg.mod:callable 形式的入口点规格说明的 .start 文件 其中 pkg.mod 是给定可调用对象的导入路径。 当 Python 启动时,将定位可调用对象并不带参数地进行调用。

在 .pth 文件中的添加 import 行的做法已被静默地弃用。 当找到匹配 .start 文件时,.pth 文件中的 import 行将被忽略。 .pth 文件中的 sys.path 扩展行没有改变。

site 模块还提供了 site.StartupState 用于多个 site 目录的批量启动处理,以确保所有静态路径扩展在执行任何启动代码之前被应用。 site.main() 会隐式地使用该类的实例在正常的解释器启动期间批量处理所有启动配置文件。 需要相同批处理行为的调用者可以直接构建一个 StartupState 并通过 addsitedir(), addusersitepackages() 和 addsitepackages() 驱动它,然后在批处理结束时调用 process() 一次。

(由 Barry Warsaw 在 gh-148641 和 gh-150228 中贡献。)

PEP 803: 针对自由线程构建的稳定 ABI

以 稳定 ABI 作为目标的 C 扩展现在可以针对新的 自由线程构建版稳定 ABI (或称 abi3t) 进行编译,这将使其能兼容 CPython 的 自由线程构建版。 这通常需要对源代码进行不小的更改;具体而言:

请注意稳定 ABI 并未提供 CPython 所必须提供的所有功能。 无法切换至 abi3t 的扩展应当继续分别针对现有的稳定 ABI (abi3) 以及自由线程版本专属 ABI (cp315t) 进行构建。

针对自由线程构建版的稳定 ABI 通常应当在构建工具中选择(举例来说,比如 Setuptools, meson-python, scikit-build-core 或 Maturin 等)。 在编写时,这些工具 并不 支持 abi3t。 如果你的工具是这种情况,则要为 cp315t 单独编译。 如果你没有使用构建工具 -- 或是正在编写这样的工具 -- 你可以像在 针对稳定 ABI 编译 中介绍的那样通过设置宏 Py_TARGET_ABI3T 来选择 abi3t。

一份关于切换到 abi3t 的实用 迁移指南。

参见

更多细节参见 PEP 803。

PEP 788: 围绕解释器终结化对 C API 的保护

在 C API 中,解释器终结化 对许多扩展来说都是一个问题,因为 附加 线程状态会永久性地挂起线程,导致死锁和其他出错问题。 此外,历史上在使用一个解释器之前安全地检测它是否激活是不可能的,当一个线程并发地删除另一个线程正尝试附加的解释器时会造成程序崩溃。

现在有几个新的 API 套件可以绕过这些问题:

  • 解释器守卫,它可以阻止解释器被终结。

  • 解释器视图,它允许线程安全地访问可能被并发地终结或删除的解释器。

  • 具有内置防终结保护的 新 API 用于自动附加和分离线程状态。

此外 PyGILState 族中的 API (最主要的是 PyGILState_Ensure() 和 PyGILState_Release()) 已被设为 soft deprecated。 目前 没有 移除它们的计划,现有的代码将继续可用,但在未来的 Python 版本中将不会有新的 PyGILState。

(由 Peter Bierma 在 gh-149101 中贡献。)

参见

详情见 PEP 788。

改进的错误消息

  • 现在当访问的属性不存在于某个对象上,但类似的属性可通过它的某个成员访问时解释器会在 AttributeError 异常中提供更有帮助的建议。

    举例来说,如果对象具有的一个属性本身暴露了所请求的名称,错误消息将建议通过该内部属性来访问它:

    from dataclasses import dataclass
    from math import pi
    
    @dataclass
    class Circle:
       radius: float
    
       @property
       def area(self) -> float:
          return pi * self.radius**2
    
    class Container:
       def __init__(self, inner: Circle) -> None:
          self.inner = inner
    
    circle = Circle(radius=4.0)
    container = Container(circle)
    print(container.area)
    

    现在运行此代码将产生更清楚的建议:

    Traceback (most recent call last):
      File "example.py", line 18, in <module>
        print(container.area)
              ^^^^^^^^^^^^^^
    AttributeError: 'Container' object has no attribute 'area'. Did you mean '.inner.area' instead of '.area'?
    
  • 当内置类型上的 AttributeError 没有莱文斯坦距离内的近似匹配时,错误消息现在会检查一个由其他语言(JavaScript、Java、Ruby、C#)中常见方法名称组成的静态表并建议 Python 的等价形式:

    >>> [1, 2, 3].push(4)
    Traceback (most recent call last):
    ...
    AttributeError: 'list' object has no attribute 'push'. Did you mean '.append'?
    
    >>> 'hello'.toUpperCase()
    Traceback (most recent call last):
    ...
    AttributeError: 'str' object has no attribute 'toUpperCase'. Did you mean '.upper'?
    

    当 Python 等价形式是一个语言构造而非方法时,提示将直接描述该构造:

    >>> {}.put("a", 1)
    Traceback (most recent call last):
    ...
    AttributeError: 'dict' object has no attribute 'put'. Use d[k] = v.
    

    当在一个不可变类型上调用可变方法时,提示将建议相应的可变类型:

    >>> (1, 2, 3).append(4)
    Traceback (most recent call last):
    ...
    AttributeError: 'tuple' object has no attribute 'append'. Did you mean to use a 'list' object?
    

    这些提示也将作用于内置类型的子类。

    (由 Matt Van Horn 在 gh-146406 中贡献。)

  • 解释器现在会在 delattr() 因属性缺失而失败时尝试提供建议。 当使用的属性名称非常接近现有的属性时,解释器将在错误消息中建议正确的属性名称。 例如:

    >>> class A:
    ...     pass
    >>> a = A()
    >>> a.abcde = 1
    >>> del a.abcdf
    Traceback (most recent call last):
    ...
    AttributeError: 'A' object has no attribute 'abcdf'. Did you mean: 'abcde'?
    

    (由 Nikita Sobolev 和 Pranjal Prajapati 在 gh-136588 中贡献。)

  • 一些不正确地使用术语 "argument" 的错误消息已被修正。 (由 Stan Ulbrych 在 gh-133382 中贡献。)

其他语言特性修改

  • Python 现在使用 UTF-8 作为默认编码格式,而不依赖于系统的环境。 这意味着未显式指定编码格式的 I/O 操作,例如 open('flying-circus.txt') 将会使用 UTF-8。 UTF-8 是受到广泛支持的 Unicode 字符编码格式,它已成为用于表示文本的 事实 标准,包括因特网上几乎所有的网页、编程语言等等。

    此设置仅在未给出 encoding 参数时会被应用。 为获得最佳的 Python 版本兼容性,请确保始终提供显式的 encoding 参数。 可选编码格式警告 可被用来标识可能受到此项更改影响的代码。 特殊的 encoding='locale' 参数将使用当前语言区域的编码格式,自 Python 3.10 起已受到支持。

    要保留之前版本的行为,Python 的 UTF-8 模式可通过 PYTHONUTF8=0 环境变量或 -X utf8=0 命令行选项来禁用。

    (由 Adam Turner 在 gh-133711 中贡献;PEP 686 由 Inada Naoki 撰写。)

    参见

    更多细节参见 PEP 686。

  • 解释器帮助 (如 python --help) 现在将以彩色显示。 这可通过 环境变量 来控制。 (由 Hugo van Kemenade 在 gh-148766 中贡献。)

  • 不可引发的异常现在默认以彩色高亮显示。 这可通过 环境变量 来控制。 (由 Peter Bierma 在 gh-134170 中贡献。)

  • 在 argparse, ast, calendar, difflib, http.server, pickletools, PyREPL tab completion, python --help, sqlite3, timeit, tokenize, unraisable exceptions 和 stdlib (ast, compileall, doctest, gzip, inspect, json.tool, pdb, profiling.sampling, random, regrtest, sqlite3, timeit, tokenize, trace, unittest, uuid, zipapp, zipfile) 的 CLI 帮助中添加更多色彩。

  • 现在 ImportError 和 ModuleNotFoundError 的 __repr__() 当 "name" 和 "path" 在构造时作为关键字参数给出时会将其显示为 name=<name> 和 path=<path>。 (由 Serhiy Storchaka, Oleg Iarygin 和 Yoav Nir 在 gh-74185 中贡献。)

  • 现在 __dict__ 和 __weakref__ 描述器将使用每解释器单独描述器实例,并在所有需要它们的类型间共享。 这将加快类创建速度,并有助于避免引用循环。 (由 Petr Viktorin 在 gh-135228 中贡献。)

  • 现在 -W 选项和 PYTHONWARNINGS 环境变量可以指定正则表达式代替字符串字面值来匹配警告消息和模块名称,这时相应的字段要以正斜杠 (/) 打头和结尾。 (由 Serhiy Storchaka 在 gh-134716 中贡献。)

  • 接受 timestamp 或 timeout 参数的函数现在可接受任意实数 (如 Decimal 和 Fraction),而不只是整数或浮点数,虽然这并不会提升精度。 (由 Serhiy Storchaka 在 gh-67795 中贡献。)

  • 增加 bytearray.take_bytes(n=None, /) 从 bytearray 获取字节串而无需拷贝。 这允许优化需要在处理可变字节缓冲区返回 bytes 的代码比如数据缓冲、网络协议解析、编码、解码和压缩等。 下面列出了可以用 take_bytes() 来优化的常见代码模式。

    建议的优化重构

    描述

    旧写法

    新写法

    在操作 bytearray 之后返回 bytes

    def read() -> bytes:
        buffer = bytearray(1024)
        ...
        return bytes(buffer)
    
    def read() -> bytes:
        buffer = bytearray(1024)
        ...
        return buffer.take_bytes()
    

    清空缓冲区并获取字节串

    buffer = bytearray(1024)
    ...
    data = bytes(buffer)
    buffer.clear()
    
    buffer = bytearray(1024)
    ...
    data = buffer.take_bytes()
    

    以指定的分隔符拆分缓冲区

    buffer = bytearray(b'abc\ndef')
    n = buffer.find(b'\n')
    data = bytes(buffer[:n + 1])
    del buffer[:n + 1]
    assert data == b'abc\n'
    assert buffer == bytearray(b'def')
    
    buffer = bytearray(b'abc\ndef')
    n = buffer.find(b'\n')
    data = buffer.take_bytes(n + 1)
    

    以指定分隔符拆分缓冲区;丢弃分隔符之后的内容

    buffer = bytearray(b'abc\ndef')
    n = buffer.find(b'\n')
    data = bytes(buffer[:n])
    buffer.clear()
    assert data == b'abc'
    assert len(buffer) == 0
    
    buffer = bytearray(b'abc\ndef')
    n = buffer.find(b'\n')
    buffer.resize(n)
    data = buffer.take_bytes()
    

    (由 Cody Maloney 在 gh-139871 中贡献。)

  • 许多与编译或解析 Python 代码相关的函数,比如 compile(), ast.parse(), symtable.symtable() 和 importlib.abc.InspectLoader.source_to_code() 等,现在允许传入模块名称。 这在无歧义地基于模块名称 过滤 语法警告时是必需的。 (由 Serhiy Storchaka 在 gh-135801 中贡献。)

  • 允许为任何类定义 __dict__ 和 __weakref__ __slots__。 (由 Serhiy Storchaka 在 gh-41779 中贡献。)

  • 允许为派生自 tuple 的类(包括由 collections.namedtuple() 创建的类定义任何 __slots__。 (由 Serhiy Storchaka 在 gh-41779 中贡献。)

  • 现在 slice 类型支持下标操作,使其成为 generic type。 (由 James Hilton-Balfe 在 gh-128335 中贡献。)

  • 现在 memoryview 类支持 float complex 和 double complex C 类型:分别对应格式字符 'Zf' 和 'Zd'。 (由 Victor Stinner 在 gh-146151 和 gh-148675 中贡献。)

  • 允许 bytes.replace() 的 count 参数为关键字参数。 (由 Stan Ulbrych 在 gh-147856 中贡献。)

  • 现在 match 字面值模式中可接受单目加号,对应对单目减号的现有支持。 (由 Bartosz Sławecki 在 gh-145239 中贡献。).)

  • 导入系统现在会以层级顺序获取每模块锁(父包在其子包之前)。 这修复了长期存在的一个导入 pkg.sub 的线程和另一个导入 pkg.sub.mod 的线程在 pkg/sub/__init__.py 导入 pkg.sub.mod 时可能发生相互阻塞的死锁问题。 (由 Gregory P. Smith 在 gh-83065 中贡献。)

  • 使用 .so 后缀的稳定 ABI 扩展的文件名现在可以包括由多架构标识组成的元组,例如 foo.abi3-x86-64-linux-gnu.so。 这将允许针对多种架构的稳定 ABI 扩展同时安装在同一目录中,不会相互冲突,就像常规动态扩展一样。 (由 Stefano Rivera 在 gh-122931 中贡献。)

  • 模块上的 __cached__ 属性,自 3.13 版起被弃用,已不再被导入系统纳入考虑。 请改用 __spec__.cached。 (由 Brett Cannon 在 gh-97879 中贡献。)

    请注意 __loader__ 和 __package__ 属性也已被弃用并计划要移除。

默认的交互式 shell

  • 现在 Tab 补全将按对象类别以彩色显示,该功能基于 fancycompleter。 设置 PYTHON_BASIC_COMPLETER 可回退至 rlcompleter。 颜色还可通过 环境变量 来控制。 (由 Antonio Cuni 和 Pablo Galindo 在 gh-130472 中贡献。)

  • Tab 补全现在会在 from ... import 语句中提供模块属性建议。 只有在模块被导入后才会有属性建议,因此 stdlib 模块将被自动导入;而对于其他模块,当第二次按下 Tab 时补全器才会导入它们。 (由 Loïc Simon 和 Pablo Galindo 在 gh-140870 中贡献。)

新增模块

math.integer

该模块提供对整数参数的数学函数的访问 (PEP 791)。 (由 Serhiy Storchaka 在 gh-81313 中贡献。)

改进的模块

argparse

  • 现在 BooleanOptionalAction 动作支持单连字符长选项和替代前缀字符。 (由 Serhiy Storchaka 在 gh-138525 中贡献。).)

  • 将 argparse.ArgumentParser 的 suggest_on_error 形参默认值改为 True。 这将默认启用为输入错误的参数提供建议。 (由 Jakob Schluse 在 gh-140450 中贡献。)

  • 在 ArgumentParser 描述和结语文本中增加反引号标记支持以便在彩色输出被启用时高亮显示内联代码。 (由 Savannah Ostrowski 在 gh-142390 中贡献。)

  • 将反引号标记扩展至参数 help 文本并增加对双重反引号(RST 内联字面值样式)的支持。 (由 Hugo van Kemenade 在 gh-149375 中贡献。)

array

  • 支持 float complex 和 double complex C 类型:分别对应格式字符 'Zf' 和 'Zd'。 (由 Victor Stinner 在 gh-146151 和 gh-148675 中贡献。)

  • 支持半精度浮点数(16 位 IEEE 754 二进制交换格式):对应格式字符 'e'。 (由 Sergey B Kirpichev 在 gh-146238 中贡献。)

  • 将 array.typecodes 类型从 str 更改为 tuple 以支持多于 1 个字符的类型代码 (Zf 和 Zd)。 (由 Victor Stinner 在 gh-148675 中贡献。)

ast

  • 为 dump() 增加 color 形参。 如果为 True,则返回的字符串将使用 ANSI 转义序列设置语法高亮。 如果为 False (默认值),则始终禁用彩色输出。 (由 Stan Ulbrych 在 gh-148981 中贡献。)

  • 现在 命令行 输出默认使用语法高亮。 这可以 使用环境变量来控制。 (由 Stan Ulbrych 在 gh-148981 中贡献。)

asyncio

  • 增加 TaskGroup.cancel 以允许提前终结任务分组,例如,当任务目标已达成或者其服务不再需要时。 在之前版本中这会涉及反直觉的特殊处理比如由一个额外任务引发自定义异常然后在退出任务分组时抑制该异常。 (由 John Belmonte 在 gh-127214 中贡献。).)

base64

binascii

calendar

  • calendar 的 命令行 文本输出将使用更多彩色。 这可以通过 环境变量 来控制。 (由 Hugo van Kemenade 在 gh-148352 中贡献。)

  • calendar 的 命令行 HTML 输出现在接受 year-month 选项: python -m calendar -t html 2009 06。 (由 Pål Grønås Drange 在 gh-140212 中贡献。)

  • 由 calendar.HTMLCalendar 类生成的日期页现在支持深色模式并已迁移至 HTML5 标准已提升可访问性。 (由 Jiahao Li 和 Hugo van Kemenade 在 gh-137634 中贡献。)

collections

  • 增加 collections.Counter.__xor__() 和 collections.Counter.__ixor__() 用于计算 Counter 对象间的对称差。 (由 Raymond Hettinger 在 gh-138682 中贡献。)

concurrent.futures

contextlib

ctypes

dataclasses

  • 针对已生成 __init__ 方法的标注不再包括内部类型名称。 (由 David Ellis 在 gh-137530 中贡献。)

dbm

  • 向 dbm.dumb 和 dbm.sqlite3 添加新的 reorganize() 方法用于回收先前被已删除条目占用的未使用空闲空间。 (由 Andrea Oliveri 在 gh-134004 中贡献。).)

difflib

  • 向 difflib.unified_diff() 引入可选的 color 形参,启用类似于 git diff 的彩色输出。 这可通过 环境变量 来控制。 (由 Douglas Thor 在 gh-133725 中贡献。)

  • 改进了由 difflib.HtmlDiff 类生成的 HTML diff 页面的样式,并将输出迁移至 HTML5 标准。 (由 Jiahao Li 在 gh-134580 中贡献。)

email

  • 现在当 EmailMessage 由于地址头中存在非 ASCII 邮箱地址 (mailbox) 而无法准确展平时邮箱生成器会引发一个错误。 用于支持 Email Address Internationalization (EAI) 的选项的相关讨论见 EmailPolicy.utf8。 (由 R David Murray 和 Mike Edmunds 在 gh-122540 中贡献。)

faulthandler

functools

gc

  • Python 3.14.0-3.14.4 使用了新的增量式垃圾收集器。 不过,由于大量在生产环境中出现显著内存压力的 报告,它已被改回 3.13 中的世代式 GC。 这是目前 Python 3.14.5 及之后版本以及 Python 3.15 中使用的 GC。 (由 Sergey Miryanov 在 gh-148726 中贡献。)

hashlib

  • 确保哈希函数肯定会作为 hashlib 的属性存在并始终 可用 即使它们在运行时由于缺少后端实现而无法运作。 例如,hashlib.md5 当 OpenSSL 不可用且 Python 构建不带 MD5 支持时将不再引发 AttributeError。 (由 Bénédikt Tran 在 gh-136929 中贡献。)

http.client

  • 向 HTTPConnection 和 HTTPSConnection 构造器增加了新的 max_response_headers 仅限关键字形参。 该形参覆盖了允许的响应标头默认最大数量。 (由 Alexander Enrique Urieles Nieto 在 gh-131724 中贡献。)

http.server

importlib.metadata

  • 在此之前,当访问一个不包含元数据文件的分发版元数据目录时,metadata() 和 Distribution.metadata 将会返回一个空的 PackageMetadata 对象就如同该文件存在但为空一样 。现在,则会引发 MetadataNotFound 异常。 请参阅 importlib_metadata#493 了解相关背景和理由并参阅 gh-143387 了解对于兼容性问题的思路。 (由 Jason R. Coombs 贡献。)

inspect

  • 为 getdoc() 增加 inherit_class_doc 和 fallback_to_class_doc 形参。 (由 Serhiy Storchaka 在 gh-132686 中贡献。)

json

  • 向 load() 和 loads() 函数添加 array_hook 形参:允许针对 JSON 字面值数组类型的回调以便自定义作为结果的已解码对象中的 Python 列表。 将组合的 frozendict 传给 object_pairs_hook 形参并将 tuple 传给 array_hook 将产生一个深度嵌套的不可变 Python 结构来表示 JSON 数据。 (由 Joao S. O. Bueno 在 gh-146440 中贡献。)

locale

math

mimetypes

mmap

  • 现在 mmap.mmap 在 Windows 上有一个 trackfd 形参;如果它是 False,则对应于 fileno 的文件句柄将不会被复制。 (由 Serhiy Storchaka 在 gh-78502 中贡献。)

  • 增加 mmap.mmap.set_name() 方法用于在 Linux 内核支持 PR_SET_VMA_ANON_NAME (Linux 5.17 或更新版本) 的情况下标注匿名内存映射。 (由 Donghee Na 在 gh-142419 中贡献。)

os

  • 在带有 glibc 2.28 以上版本的 Linux 4.11 以上内核版本上增加 os.statx()。 (由 Jeffrey Bosboom 和 Victor Stinner 在 gh-83714 中贡献。)

  • 现在 os.makedirs() 函数增加了一个 parent_mode 形参以允许指定中间目录的模式。 这可被用来通过传入 parent_mode=mode 与 Python 3.6 及更早版本的行为相匹配。 (由 Zackery Spytz 和 Gregory P. Smith 在 gh-86533 中贡献。)

os.path

pathlib

  • 现在 pathlib.Path.mkdir() 增加了 parent_mode 形参以允许在 parents=True 时指定中间目录的模式。 (由 Gregory P. Smith 在 gh-86533 中贡献。)

pdb

  • 使用新的交互式 shell 作为 pdb 默认的输入 shell。 (由 Tian Gao 在 gh-145379 中贡献。)

pickle

  • 增加对封存私有方法和嵌套类的支持。 (由 Zackery Spytz 和 Serhiy Storchaka 在 gh-77188 中贡献。)

pickletools

pprint

re

  • 现在 re.prefixmatch() 和相应的 re.Pattern.prefixmatch() 作为现有的已设为 soft deprecated 的 re.match() 和 re.Pattern.match() API 的替代性的、更明白的显式名称被添加。 这样做的目的是为了遵循 Python 之禅的 "明白胜于隐晦" 原则以消除对 match 具体含义理解所造成的混淆。 大多数其他语言的正则表达式库都使用名为 match 的 API 来表示 Python 一直以来所称的 search。 (由 Gregory P. Smith 在 gh-86519 中贡献。)

resource

shelve

  • 向 shelve 添加新的 reorganize() 方法用于回收先前被已删除条目占用的未使用空闲空间。 (由 Andrea Oliveri 在 gh-134004 中贡献。)

  • 在 shelve 模块中增加对自定义序列化和反序列化函数的支持。 (由 Furkan Onder 在 gh-99631 中贡献。)

socket

  • 增加针对 ISO-TP CAN 协议的常量。 (由 Patrick Menschel 和 Stefan Tatschner 在 gh-86819 中贡献。)

sqlite3

  • 命令行界面 增加了一些新特性:

    • 在按 Tab 时提供 SQL 关键字补全。 (由 Long Tan 在 gh-133393 中贡献。)

    • 提示、错误消息和帮助文本现在使用彩色。 此特性默认启用,详情参见 控制颜色。 (由 Stan Ulbrych 和 Łukasz Langa 在 gh-133461 中贡献。)

    • 在 Tab 时提供表、索引、触发器、视图、列、函数和模式补全。 (由 Long Tan 在 gh-136101 中贡献。)

ssl

  • 通过 ssl.HAS_PSK_TLS13 指明 ssl 模块是否支持 TLSv1.3 中的 "External PSKs",具体描述见 RFC 9258。 (由 Will Childs-Klein 在 gh-133624 中贡献。)

  • 增加一些新方法用于管理 SSL 密钥协议所使用的分组:

    • ssl.SSLContext.set_groups() 用于设置允许执行密钥协商的分组,扩展了之前的 ssl.SSLContext.set_ecdh_curve() 方法。 这个新 API 提供了列出多个分组的功能并支持固定字段以及 ECDH 曲线以外的后量子群组。 此方法还可用于控制在 TLS 握手时要发送哪些密钥分量。

    • ssl.SSLSocket.group() 将返回在 TLS 握手完成后被选定用于对当前连接执行密钥协商的分组。 此调用需要 OpenSSL 3.2 或更高版本。

    • ssl.SSLContext.get_groups() 将返回一个与当前上下文中设置的最小和最大 TLS 版本兼容的所有可用密钥协商分组的列表。 此调用需要 OpenSSL 3.5 或更高版本。

    (由 Ron Frederick 在 gh-136306 中贡献。)

  • 新增一个 ssl.SSLContext.set_ciphersuites() 方法用于设置 TLS 1.3 密码套件。 对于 TLS 1.2 或更早版本,应当继续使用 ssl.SSLContext.set_ciphers()。 这两个调用均可在同一上下文中执行而所选的密码套件将取决于建立连接时协商的 TLS 版本。 (由 Ron Frederick 在 gh-137197 中贡献。)

  • 增加一些新方法用于管理签名算法:

    (由 Ron Frederick 在 gh-138252 中贡献。)

subprocess

  • subprocess.Popen.wait(): 在 timeout 不为 None 且平台支持时,将使用高效的事件驱动机制来等等进程终结:

    如果这些机制都不可用,该函数将回退到传统的忙状态循环(非阻塞调用和短暂休眠)。 (由 Giampaolo Rodola 在 gh-83069 中贡献。)

symtable

sys

  • 增加 sys.abi_info 命名空间来改善对 ABI 信息的访问。 (由 Klaus Zimmermann 在 gh-137476 中贡献。)

sys.monitoring

tarfile

  • data_filter() 现在会对符号链接目标进行规范化处理,以避免路径遍历攻击。(由 Petr Viktorin 在 gh-127987 和 CVE 2025-4138 中贡献。)

  • 当一个目录被移除或被另一种文件替代时 extractall() 现在会跳过修复目录属性。 (由 Petr Viktorin 在 gh-127987 和 CVE 2024-12718 中贡献。).)

  • 在将一个链接(硬链接或符号链接)替换为另一个归档成员的副本,以及在修复目录属性时 extract() 和 extractall() 现在会(重新)应用提取过滤器。 前者将引发一个新的异常,LinkFallbackError。 (由 Petr Viktorin 为 CVE 2025-4330 和 CVE 2024-12718 贡献。)

  • 当 errorlevel() 为零时 extract() 和 extractall() 将不再提取被拒绝的成员。 (由 Matt Prodani 和 Petr Viktorin 在 gh-112887 和 CVE 2025-4435 中贡献。)

  • 现在 extract() 和 extractall() 在 Windows 上会将符号链接目标中的斜杠替换为反斜杠以防止创建损坏的链接。 (由 Christoph Walcher 在 gh-57911 中贡献。)

  • 现在 gettarinfo() 在 Windows 上会将符号链接目标中的反斜杠替换为斜杠以符合 tar 格式标准。 (由 Daniele Nicolodi 在 gh-151669 中贡献。)

threading

timeit

  • timeit 命令行接口的输出默认使用彩色。 这可以通过 环境变量 进行控制。 (由 Hugo van Kemenade 在 gh-146609 中贡献。)

  • 命令行界面现在默认以彩色显示错误回溯信息。 这可以通过 环境变量 来控制。 (由 Yi Hong 在 gh-139374 中贡献。)

  • 将 timeit.Timer.autorange() 的目标时间设为可配置并向命令行界面添加 --target-time 选项。 (由 Alessandro Cucci 和 Miikka Koskinen 在 gh-80642 中贡献。)

tkinter

  • 现在 tkinter.Text.search() 方法支持两个附加参数: nolinestop 允许跨越行边界继续搜索;以及 strictlimits 限制在指定范围内进行搜索。 (由 Rihaan Meher 在 gh-130848 中贡献。)

  • 引入一个新方法 tkinter.Text.search_all()。 此方法允许使用 Tcl 的 -all 和 -overlap 选项来搜索所有符合特定模式的匹配项。 (由 Rihaan Meher 在 gh-130848 中贡献。)

  • 新增 pack_content(), place_content() 和 grid_content() 方法来使用具有新名称的 Tk 命令(在 Tk 8.6 中引入)以取代使用具有过时名称的 Tk 命令的 *_slaves() 方法。 (由 Serhiy Storchaka 在 gh-143754 中贡献。)

  • 增加 Event 属性 user_data 用于 Tk 虚拟事件并增加 detail 用于 Enter, Leave, FocusIn, FocusOut 和 ConfigureRequest 事件。 (由 Matthias Kievernagel 和 Serhiy Storchaka 在 gh-47655 中贡献。)

tokenize

tomllib

  • 现在 tomllib 模块支持 TOML 1.1.0。 这是个向下兼容的更新,意味着所有合法的 TOML 1.0.0 文档都将以同样的方式被解析。

    根据 official TOML changelog,有下列改变:

    • 允许在内联表格中使用换行符和末尾逗号。

      在此之前内联表格必须位于单行内且不能以末尾逗号结束。 现在已放宽限制因此以下代码将是有效的:

      tbl = {
         key      = "a string",
         moar-tbl =  {
            key = 1,
         },
      }
      
    • 为基础字符串添加 \xHH 表示法用于 255 以下的码点,以及 \e 表示法用于转义字符:

      null = "null byte: \x00; letter a: \x61"
      csi = "\e["
      
    • 现在 datetime 和 time 值中的秒数是可选的。 以下写法现在均有效:

      dt = 2010-02-03 14:15
      t  = 14:15
      

    (由 Taneli Hukkinen 在 gh-142956 中贡献。)

types

typing

  • PEP 747: 增加 TypeForm,这是一个新的用于标注本身属于类型表达式的值的特殊形式。 TypeForm[T] 表示 "一个描述 T (或可赋值给 T 的类型) 的类型形式对象"。 在运行时,TypeForm(x) 将简单地返回 x,这将允许类型形式值的显式标注而无需更改行为。

    这有助于那些接受用户提供类型表达式 (例如 int, str | None, TypedDict 的类工,或 list[int]) 的库对外暴露精确的签名:

    from typing import Any, TypeForm
    
    def cast[T](typ: TypeForm[T], value: Any) -> T: ...
    

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

  • PEP 728: 在 TypedDict 中添加对 closed 和 extra_items 类参数的支持。 如 closed 为真值则 TypedDict 不允许超出类代码体中指定范围的额外键,如 TypedDict 带有 extra_items 则允许值为指定类型的任意额外条目。 (由 Angela Liss 在 gh-137840 中贡献。)

  • 类似 class ExtraTypeVars(P1[S], Protocol[T, T2]): ... 的代码现在将引发 TypeError,因为 S 未在 Protocol 形参中列出。 (由 Nikita Sobolev 在 gh-137191 中贡献。)

  • 类似 class B2(A[T2], Protocol[T1, T2]): ... 的代码现在会正确处理类型形参顺序:它将是 (T1, T2),而非此前在运行时被错误地推断为的 (T2, T1)。 (由 Nikita Sobolev 在 gh-137191 中贡献。)

  • PEP 800: 添加 @typing.disjoint_base,这个新装饰器可将类标记为互斥基类。 这个高级特性的主要目的是允许类型检查器如实反映定义为内置对象或为已编译扩展的类型的运行时语义。 如果一个类 C 为互斥基类,那么该类的子类将无法自不是 C 的父类或子类的其他互斥基类继承。 (由 Jelle Zijlstra 在 gh-148639 中贡献。)

  • 现在 TypeVarTuple 接受 bound, covariant, contravariant 和 infer_variance 关键字参数,与 TypeVar 和 ParamSpec 的接口相匹配。 bound 的语义在规范中尚未定义。

unicodedata

unittest

urllib.parse

venv

  • 在 POSIX 平台上,platlib 目录将在创建虚拟环境时根据需要被创建,而不是使用 lib64 -> lib 符号链接。 这意味着在 sys.platlibdir 不等于 lib 的平台上虚拟环境的 purelib 和 platlib 将不再共享同一个 lib 目录。 (由 Rui Xi 在 gh-133951 中贡献。)

warnings

  • 在 warnings.warn_explicit() 中如果未传入 module 参数则会改进按模块过滤的操作。 现在它不但会针对去除 .py 的文件名,还会针对从与文件名不同的父目录开始构造的模块名称(去除 /__init__.py, .py,在 Windows 上,.pyw 也会被去除)测试警告过滤器中的模块正则表达式。 (由 Serhiy Storchaka 在 gh-135801 中贡献。)

wave

(由 Lionel Koenig 和 Michiel W. Beijen 在 gh-60729 中贡献。)

webbrowser

  • 在 macOS 上,新的 webbrowser.MacOS 类可通过 /usr/bin/open 打开 URL 而不是通过 osascript 构造并执行 AppleScript。 默认的浏览器是使用 plistlib 从 LaunchServices 首选项文件中检测到的,在新安装系统中将以 com.apple.Safari 作为回退项。 对于非 HTTP(S) URL,会使用 open -b <bundle-id> 通过浏览器而不是 OS 文件处理器对 URL 执行路由,以防止文件注册攻击。 (由 Jeff Lyon 在 gh-137586 中贡献。)

xml

  • 增加 xml.is_valid_name() 函数用于检测字符串是否可被用作 XML 中的元素或属性名称。 (由 Serhiy Storchaka 在 gh-139489 中贡献。)

  • 增加 xml.is_valid_text() 函数用于检测字符串是否可被用于 XML 文档。 (由 Serhiy Storchaka 在 gh-139489 中贡献。)

xml.parsers.expat

zlib

  • 允许通过 adler32_combine() 来合并两个 Adler-32 校验和。 (由 Callum Attryde 和 Bénédikt Tran 在 gh-134635 中贡献。)

  • 允许通过 crc32_combine() 来合并两个 CRC-32 校验和。 (由 Bénédikt Tran 在 gh-134635 中贡献。)

性能优化

base64 和 binascii

  • 现在得益于简单的 CPU 管线优化 CPython 的底层 base64 实现编码有 2x 的提速而解码有 3x 的提速。 (由 Gregory P. Smith 和 Serhiy Storchaka 在 gh-143262 中贡献。)

  • 针对 Ascii85, Base85 和 Z85 编码格式的实现已用 C 语言重写。 编码和解码速度现在提升了两个数量级并且内存消耗也减少了两个数量级。 (由 James Seo 和 Serhiy Storchaka 在 gh-101178 中贡献。)

  • 针对 Base32 的实现已用 C 语言重写。 编码和解码速度现在提升了两个数量级。 (由 James Seo 在 gh-146192 中贡献。).)

csv

  • 现在 csv.Sniffer.sniff() 定界符检测获得至多 1.6x 的加速。 (由 Maurycy Pawłowski-Wieroński 在 gh-137628 中贡献。)

升级的实验性 JIT 编译器

Results from the pyperformance benchmark suite report a 7-8% geometric mean performance improvement for the JIT over the standard CPython interpreter built with all optimizations enabled on x86-64 Linux. On AArch64 macOS, the JIT has an 11-12% speedup over the tail calling interpreter with all optimizations enabled. The speedups for JIT builds versus no JIT builds range from roughly 15% slowdown to over 100% speedup (ignoring the unpack_sequence microbenchmark) on x86-64 Linux and AArch64 macOS systems.

对 JIT 的主要升级有:

  • LLVM 21 构建时依赖

  • 新的追踪前端

  • JIT 中基本的注册分配

  • 更多的 JIT 优化

  • GDB 和 GNU backtrace() 展开支持

  • 更好的机器码生成

LLVM 21 构建时依赖

现在 JIT 编译器将为构建时的 stencil 生成使用 LLVM 21。 与往常一样,LLVM 仅在启用 JIT 构建 CPython 时才是必需的;运行 Python 的最终用户无需安装 LLVM。 针对所有受支持平台安装 LLVM 的指导见 JIT 编译器文档。 (由 Savannah Ostrowski 在 gh-140973 中贡献。)

新的追踪前端

现在 JIT 编译器相比 Python 3.14 支持更多的字节码操作和控制流,从而能够在更多的代码上实现性能加速。 例如,现在 3.15 JIT 编译器能处理简单 Python 对象创建。 重载操作和生成器也得到部分支持。 这一改进得益于经过彻底重构能够记录代码实际执行路径的 JIT 追踪前端,而不是像之前的实现那样仅进行估算。 (由 Ken Jin 在 gh-139109 中贡献。 对 Windows 的支持由 Mark Shannon 在 gh-141703 中贡献。)

JIT 中基本的注册分配

已向 JIT 编译器的优化器添加一个基本的寄存器分配形式。 这使得 JIT 编译器能完全避免特定的栈操作而是直接在寄存器上操作。 这允许 JIT 通过避免对内存的读写操作来产生更高效的执行轨迹。 (由 Mark Shannon 在 gh-135379 中贡献。)

更多的 JIT 优化

现在会执行更多的`常量传播<https://en.wikipedia.org/wiki/Constant_folding>`__ 。这意味着当JIT编译器检测到某些用户代码会导致常量 时,JIT编译器可以对该代码进行简化。(由Ken Jin和Savannah Ostrowski在:gh:132732 中贡献。)

引用计数 会在确保安全的情况下尽量避免。 这通常会减少 Python 中大多数操作的开销。 (由 Ken Jin, Donghee Na, Zheao Li, Hai Zhu, Savannah Ostrowski, Reiden Ong, Noam Cohen, Tomas Roun, PuQing, Cajetan Rodrigues, 和 Sacul 在 gh-134584 中贡献。)

通过追踪对象的唯一引用,JIT 优化器现在可以略去引用计数更新并对整数和浮点数执行原地操作。 (由 Reiden Ong 和 Pieter Eendebak 在 gh-143414 和 gh-146306 中贡献。)

现在 JIT 优化器支持的操作数量相比 3.14 大幅增加。 (由 Kumar Aditya, Ken Jin, Jiahao Li 和 Sacul 在 gh-131798 中贡献。)

GDB 和 GNU backtrace() 展开支持

在受支持的 Linux ELF 平台上 JIT 编译器现在会将所生成的机器码的展开信息发布到 GDB 接口。 当 libgcc 帧注册功能可用时,同样的展开信息也会为 GNU backtrace() 栈遍历器执行注册。 这允许使用这些机制的原生调试器、崩溃处理器和诊断工具能通过 JIT 帧进行展开而不是在生成的机器码处停止。 (由 Diego Russo 和 Pablo Galindo Salgado 在 gh-146071 和 gh-149104 中贡献。)

更好的机器码生成

现在 JIT 编译器的机器码生成器可为 x86-64 和 AArch64 macOS 以及 Linux 目标平台生成更优质的机器码。 总体而言,与targets. In general, users should experience lower memory usage for generated machine code and more efficient machine code versus 3.14 相比用户相当能体验到生成的机器码内存占用更低且机器码运行效率更高。 (由 Brandt Bucher 在 gh-136528 和 gh-135905 中贡献。) 针对 AArch64 的实现由 Mark Shannon 在 gh-139855 中贡献。 针对 AArch64 的额外优化由 Mark Shannon 和 Diego Russo 在 gh-140683 和 gh-142305 中贡献。)

可维护性

JIT 优化器的操作已得到简化。 这是通过对 JIT 数据结构进行重构来实现的。 (由 Zhongtian Zheng 在 gh-148211 中以及 Hai Zhu 在 gh-143421 中贡献。)

移除

ast

  • 当所需的参数被活力或是传入了无法映射到 AST 节点上的字段的关键字参数时 AST 节点 的构造器现在会引发 TypeError。 此前自 Python 3.13 开始这些情况会引发 DeprecationWarning。 (由 Brian Schubert 和 Jelle Zijlstra 在 gh-137600 和 gh-105858 中贡献。)

collections.abc

  • collections.abc.ByteString 已从 collections.abc.__all__ 移除。 collections.abc.ByteString 自 Python 3.12 起已被弃用,并计划在 Python 3.17 中移除。 (由 Alex Waygood 在 gh-118803 中贡献。)

ctypes

  • 移除了未写入文档的函数 ctypes.SetPointerType(),它自 Python 3.13 起已被弃用。 (由 Bénédikt Tran 在 gh-133866 中贡献。)

datetime

  • 现在 strptime() 会在格式字符串包含不带年份指示符的 %d (月份日序号) 时引发 ValueError。 这种做法自 Python 3.13 起已被弃用。 (由 Stan Ulbrych 和 Gregory P. Smith 在 gh-70647 中贡献。)

glob

  • 移除了未写入文档的 glob.glob0() 和 glob.glob1() 函数,它们自 Python 3.13 起已被弃用。 请改用 glob.glob() 并将一个目录传给其 root_dir 参数。 (由 Barney Gale 在 gh-137466 中贡献。)

http.server

  • 移除 CGIHTTPRequestHandler 类并从 python -m http.server 命令行接口移除 --cgi 旗标。 它们在 Python 3.13 中被弃用。 (由 Bénédikt Tran 在 gh-133810 中贡献。)

importlib

  • Loader 及其子类的 load_module() 方法已被移除。 当其在自定义子类上被定义时将不再被导入系统所调用。 此方法自 Python 3.4 起已被弃用而应改用 exec_module()。 (由 Brett Cannon 在 gh-97850 中贡献。)

importlib.resources

pathlib

  • 移除已被弃用的 pathlib.PurePath.is_reserved()。 在 Windows 上请使用 os.path.isreserved() 来检测保留路径。 (由 Nikita Sobolev 在 gh-133875 中贡献。)

platform

  • 移除了 platform.java_ver() 函数,它自 Python 3.13 起已被弃用。 (由 Alexey Makridenko 在 gh-133604 中贡献。)

sre_*

  • 移除了 sre_compile, sre_constants 和 sre_parse 模块。 (由 Stan Ulbrych 在 gh-135994 中贡献。)

sysconfig

threading

  • 移除了对 RLock 对象的 C 实现中任意位置或关键字参数的支持。 此特性在 Python 3.14 中已被弃用。 (由 Bénédikt Tran 在 gh-134087 中贡献。).)

types

  • 从 types.CodeType 中移除了 codeobject.co_lnotab,它自 Python 3.12 起已根据 PEP 626 弃用。 (由 Nikita Sobolev 在 gh-134690 中贡献。)

typing

  • typing.ByteString 已从 typing.__all__ 移除。 typing.ByteString 自 Python 3.9 起已被弃用,并计划在 Python 3.17 中移除。 (由 Alex Waygood 在 gh-118803 中贡献。)

  • 用于创建 NamedTuple 类的未写入文档的关键字参数语法 (例如 Point = NamedTuple("Point", x=int, y=int)) 已不再受支持。 请改用基于类的语法或函数式语法。 (由 Bénédikt Tran 在 gh-133817 中贡献。)

  • 使用 TD = TypedDict("TD") 或 TD = TypedDict("TD", None) 来构造零字段的 TypedDict 类型已不再受支持。 请改用 class TD(TypedDict): pass 或 TD = TypedDict("TD", {})。 (由 Bénédikt Tran 在 gh-133823 中贡献。)

  • 移除了被弃用的 @typing.no_type_check_decorator。 (由 Nikita Sobolev 在 gh-133601 中贡献。)

wave

  • 移除了 Wave_read 和 Wave_write 类的 getmark(), setmark() 和 getmarkers() 方法,它们自 Python 3.13 起已被弃用。 (由 Bénédikt Tran 在 gh-133873 中贡献。)

zipimport

弃用

新的弃用

  • ast:

    • 创建抽象 AST 节点 (如 ast.AST 或 ast.expr) 的做法已被弃用并将在 Python 3.20 中引发错误。

      (由 Brian Schubert 在 gh-116021 中贡献。)

  • base64:

    • 在 b64decode() 和 urlsafe_b64decode() 中接受 + 和 / 字符带替换字母表的做法现已被弃用。 在未来的 Python 版本中它们会成为严格模式下的错误并会在非严格模式下被丢弃。 (由 Serhiy Storchaka 在 gh-125346 中贡献。)

  • CLI:

    • 弃用 -b 和 -bb 命令行选项并计划在 Python 3.17 中将它们设为空操作。 它们是主要用于 Python 2 -> 3 转换的辅助工具。 从 Python 3.17,将不再针对这些情况引发 BytesWarning;请改用类型检查器。

      (由 Nikita Sobolev 在 gh-136355 中贡献。)

  • collections.abc:

    • 在运行时以下语句现在将导致发出 DeprecationWarning:

      • from collections.abc import ByteString

      • import collections.abc; collections.abc.ByteString

      如果 collections.abc.ByteString 被子类化或是被用作传给 isinstance() 或 issubclass() 则 DeprecationWarning 会被发出,但如果只是被导入或是从 collections.abc 模块访问则不会提前发出。 (由 Alex Waygood 在 gh-118803 中贡献。)

  • hashlib:

    • 在哈希函数构造器如 new() 或者直接使用哈希算法名称的构造器如 md5() 和 sha256() 中,可选的初始数据形参在不同的 hashlib 实现中也可使用名为 data= 或 string= 的关键字参数形式传入。

      对 string 关键字参数名的支持现已被弃用并计划在 Python 3.19 中移除。 建议将初始数据作为位置参数传入以获得最大的向下兼容性。

      (由 Bénédikt Tran 在 gh-134978 中贡献。)

  • http.cookies:

  • imaplib:

    • 修改 IMAP4.file 的做法现已被弃用并计划在 Python 3.19 中移除。 该属性现已不再使用并且修改其值 不会 显式地关闭当前文件。 (由 Bénédikt Tran 在 gh-142307 中贡献。)

  • profile:

    • profile 模块已被弃用并将在 Python 3.17 中移除。 请改用 profiling.tracing,它提供了兼容的 API。 详情参见 PEP 799。 (由 Pablo Galindo 和 László Kiss Kollár 在 gh-138122 中贡献。)

  • re:

    • 现在 re.match() 和 re.Pattern.match() 已被设为 soft deprecated 而应改用新的 re.prefixmatch() 和 re.Pattern.prefixmatch() API,它们作为替代性的、更明白的显式名称被添加进来。 这样做的目的是为了遵循 Python 之禅的 "明白胜于隐晦" 原则以消除对 match 具体含义理解所造成的混淆。 大多数其他语言的正则表达式库都使用名为 match 的 API 来表示to mean what Python 一直以来所称为的 search。

      我们 没有 计划移除旧的 match() 名称,因为它已在代码中使用超过 30。 支持较旧 Python 的代码应当继续使用 match(),而新的代码应当首选 prefixmatch()。 参见 prefixmatch() vs. match()。

      (由 Gregory P. Smith 在 gh-86519 以及 Hugo van Kemenade 在 gh-148100 中贡献。)

  • struct:

    • 调用 Struct.__new__() 时不再必需参数的做法现已被弃用并将在 Python 3.20 中移除。 在已初始化的 Struct 对象上调用 __init__() 方法的做法已被弃用并将在 Python 3.20 中移除。

      (由 Sergey B Kirpichev 和 Serhiy Storchaka 在 gh-143715 中贡献。).)

    • 使用 'F' 和 'D' 类型代码的做法现已被设为 soft deprecated 并应改用两字母形式 'Zf' 和 'Zd'。 (由 Sergey B Kirpichev 在 gh-121249 中贡献。).)

  • typing:

    • 在运行时以下语句现在将导致发出 DeprecationWarning:

      • from typing import ByteString

      • import typing; typing.ByteString

      如果 typing.ByteString 被子类化或是被用作传给 isinstance() 或 issubclass() 的第二个参数则会发出``DeprecationWarning``,但如果只是从 typing 模块导入或访问则不会提前发出。 (由 Alex Waygood 在 gh-118803 中贡献。)

    • 在未显式地使用 runtime_checkable() 来装饰但继承自运行时可检测协议类的协议类上调用 isinstance() 和 issubclass() 检测的做法已被弃用。 在 Python 3.20 中这会引发 TypeError。

      (由 Bartosz Sławecki 在 gh-132604 中贡献。)

  • webbrowser:

    • webbrowser.MacOSXOSAScript 已被弃用而应改用 webbrowser.MacOS 并计划在 Python 3.17 中移除。 (由 Jeff Lyon 在 gh-137586 中贡献。)

  • __version__:

计划在 Python 3.16 中移除

计划在 Python 3.17 中移除

  • datetime:

    • 使用不带年份的包含 %e (月份日期序号) 的格式字符串的 strptime() 调用自 Python 3.15 起已被弃用。 (由 Stan Ulbrych 在 gh-70647 中贡献。)

  • collections.abc:

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

      使用 isinstance(obj, collections.abc.Buffer) 来在运行时测试 obj 是否实现了 缓冲区协议。要用于类型标注,则使用 Buffer 或者显式指明你的代码所支持的类型的并集 (例如 bytes | bytearray | memoryview)。

      ByteString 原本是想作为 bytes 和 bytearray 的超类型的抽象基类提供。 不过,由于该 ABC 从未有过任何方法,知道一个对象是 ByteString 的实例并不能真正告诉你有关该对象的任何有用信息。 其他常见缓冲区类型如 memoryview 同样不能被当作是 ByteString 的子类型(无论是在运行时还是对于静态类型检查器)。

      请参阅 PEP 688 了解详情。 (由 Shantanu Jain 在 gh-91896 中贡献。)

  • encodings:

  • profile:

    • profile 模块已被弃用并将在 Python 3.17 中移除。 请改用 profiling.tracing,它提供了兼容的 API。 详情参见 PEP 799。 (由 Pablo Galindo 和 László Kiss Kollár 在 gh-138122 中贡献。)

  • webbrowser:

    • webbrowser.MacOSXOSAScript 已被弃用并改用 webbrowser.MacOS。 (gh-137586)

  • 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 原本是想作为 bytes 和 bytearray 的超类型的抽象基类提供。 不过,由于该 ABC 从未有过任何方法,知道一个对象是 ByteString 的实例并不能真正告诉你有关该对象的任何有用信息。 其他常见缓冲区类型如 memoryview 同样不能被当作是 ByteString 的子类型(无论是在运行时还是对于静态类型检查器)。

      请参阅 PEP 688 了解详情。 (由 Shantanu Jain 在 gh-91896 中贡献。)

  • tkinter:

    • tkinter.Variable 的方法 trace_variable(), trace() (trace_variable() 的别名), trace_vdelete() 和 trace_vinfo(),自 Python 3.14 起已被弃用,计划在 Python 3.17 中移除。 请改用 trace_add(), trace_remove() 和 trace_info()。 (由 Serhiy Storchaka 在 gh-120220 中贡献。)

计划在 Python 3.18 中移除

  • 当需要一个文件描述符时将不再接受布尔值。 (由 Serhiy Storchaka 在 gh-82626 中贡献。)

  • decimal:

    • 非标准且未写入文档的 Decimal 格式说明符 'N',它仅在 decimal 模块的 C 实现中受到支持,自 Python 3.13 起已被弃用。 (由 Serhiy Storchaka 在 gh-89902 中贡献。)

  • 由 PEP 829 定义的弃用:

    • 在 name.pth 文件中的 import 行会被静默地忽略。

    (由 Barry Warsaw 在 gh-148641 中贡献。)

计划在 Python 3.19 中移除

  • ctypes:

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

  • hashlib:

    • 在哈希函数构造器如 new() 或者直接使用哈希算法名称的构造器如 md5() 和 sha256() 中,它们可选的初始数据形参在不同的 hashlib 实现中也可使用名为 data= 或 string= 的关键字参数形式传入。

      对 string 关键字参数名称的支持现已被弃用并计划在 Python 3.19 中移除。

      在 Python 3.13 之前,string 关键字形参没有根据哈希函数的后端实现得到正确的支持。 建议将初始数据作为位置参数传入以获得最大的向下兼容性。

  • http.cookies:

  • imaplib:

    • 修改 IMAP4.file 的做法现已被弃用并计划在 Python 3.19 中移除。 该属性现已不再使用并且修改其值不会自动关闭当前文件。

      在 Python 3.14 之前,该属性被用于为 IMAP4 实现相应的 read() 和 readline() 方法但在此之后情况已发生改变。

计划在 Python 3.20 中移除

计划在未来版本中移除

以下 API 将会被移除,尽管具体时间还未确定。

  • argparse:

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

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

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

  • builtins:

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

    • 目前 Python 接受数字类字面值后面紧跟关键字的写法,例如 0in x, 1or x, 0if 1else 2。它允许像 [0x1for x in y] 这样令人困惑且有歧义的表达式 (它可以被解读为 [0x1 for x in y] 或者 [0x1f or x in y])。如果数字类字面值后面紧跟关键字 and, else, for, if, in, is 和 or 中的一个将会引发语法警告。在未来的版本中它将改为语法错误。 (gh-87999)

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

    • 对 __float__() 方法返回 float 的子类的支持:将要求这些方法必须返回 float 的实例。

    • 对 __complex__() 方法返回 complex 的子类的支持:将要求这些方法必须返回 complex 的实例。

    • 传入一个复数作为 complex() 构造器中的 real 或 imag 参数的做法现在已被弃用;它应当仅作为单个位置参数被传入。(由 Serhiy Storchaka 在 gh-109218 中贡献。)

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

  • codecs: codecs.open() 请改用 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()。

  • os.path: os.path.commonprefix() 已弃用,对于路径前缀请使用 os.path.commonpath()。 os.path.commonprefix() 函数被弃用是由于其误导性的名称和模块。 使用该函数获取路径前缀是不安全的,尽管它被包括在一个用于操作路径的模块中,使用此函数很容易意外地将路径遍历安全漏洞引入 Python 程序中。

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

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

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

  • ssl 选项和协议:

    • ssl.SSLContext 不带 protocol 参数的做法已被弃用。

    • 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()。

软弃用

尚无计划移除 soft deprecated API。

  • 现在 re.match() 和 re.Pattern.match() 已被设为 soft deprecated 而应改用新的 re.prefixmatch() 和 re.Pattern.prefixmatch() API,它们作为替代性的、更明白的显式名称被添加进来。 这样做的目的是为了遵循 Python 之禅的 "明白胜于隐晦" 原则以消除对 match 具体含义理解所造成的混淆。 大多数其他语言的正则表达式库都使用名为 match 的 API 来表示to mean what Python 一直以来所称为的 search。

    我们 没有 计划移除旧的 match() 名称,因为它已在代码中使用超过 30。 支持较旧 Python 的代码应当继续使用 match(),而新的代码应当首选 prefixmatch()。 参见 prefixmatch() vs. match()。

    (由 Gregory P. Smith 在 gh-86519 以及 Hugo van Kemenade 在 gh-148100 中贡献。)

  • 使用 struct 模块的 'F' 和 'D' 格式类型代码的做法现在已被设为 soft deprecated 并应改用两字母形式 'Zf' 和 'Zd'。 (由 Sergey B Kirpichev 在 gh-121249 中贡献。)

C API 的变化

新的特性

被改变的 C API

被移除的 C API

  • 移除已弃用的 PyUnicode 函数:

    • PyUnicode_AsDecodedObject(): 改用 PyCodec_Decode()。

    • PyUnicode_AsDecodedUnicode(): 改用 PyCodec_Decode();请注意某些编解码器 (例如 "base64") 可能返回 str 以外的类型,比如 bytes。

    • PyUnicode_AsEncodedObject(): 改用 PyCodec_Encode()。

    • PyUnicode_AsEncodedUnicode(): 改用 PyCodec_Encode();请注意某些编解码器 (例如 "base64") 可能返回 bytes 以外的类型,比如 str。

    (由 Stan Ulbrych 在 gh-133612 中贡献。)

  • PyImport_ImportModuleNoBlock(): 已弃用的 PyImport_ImportModule() 的别名。 (由 Bénédikt Tran 在 gh-133644 中贡献。)

  • PyWeakref_GetObject() 和 PyWeakref_GET_OBJECT: 改用 PyWeakref_GetRef()。 在 Python 3.12 及更旧的版本中可以使用 pythoncapi-compat project 来获取 PyWeakref_GetRef()。 (由 Bénédikt Tran 在 gh-133644 中贡献。)

  • 移除了已弃用了 PySys_ResetWarnOptions()。 改为清除 sys.warnoptions 和 warnings.filters。

    (由 Nikita Sobolev 在 gh-138886 中贡献。)

以下函数已被移除而应改用 PyConfig_Get()。 在 Python 3.13 及更旧的版本中可以使用 pythoncapi-compat project 来获取 PyConfig_Get()。

已弃用的 C API

构建的改变

  • 移除隐式回退至捆绑的 libmpdec 库副本的设置。 现在该设置应当通过将 --with-system-libmpdec 设为 no 或通过 --without-system-libmpdec 来显式地启用。 (由 Sergey B Kirpichev 在 gh-115119 中贡献。)

  • 新的配置选项 --with-missing-stdlib-config=FILE 允许分发方针对缺失或分开打包的 standard library 模块传递一个包含自定义错误消息的 JSON 配置文件。 (由 Stan Ulbrych 和 Petr Viktorin 在 gh-139707 中贡献。)

  • 新的配置选项 --with-pymalloc-hugepages 可为 pymalloc 区域启用巨大分页支持。 当启用时,区域大小将提高至 2 MiB 且分配将使用 MAP_HUGETLB (Linux) 或 MEM_LARGE_PAGES (Windows) 并可自动回退至常规分页。 在 Windows 上,请使用 build.bat --pymalloc-hugepages。 在运行时,巨大分页必须通过将 PYTHON_PYMALLOC_HUGEPAGES 环境变量设为 1 来显式地启用。 (由 Pablo Galindo Salgado 在 gh-144319 中贡献。)

  • 现在如果 Linux 内核支持 PR_SET_VMA_ANON_NAME (Linux 5.17 或更新版本) 则标注匿名 mmap 的用法将被支持。 如果内核支持此特性并已将 -X dev 传入 Python,或者 Python 是使用 调试模式 构建的则标注将在``/proc/<pid>/maps`` 中可见。 (由 Donghee Na 在 gh-141770 中贡献。)

  • 现在 CPython 构建默认将启用帧指针 (PEP 831)。 传入 --without-frame-pointers 可禁用此特性。

    C 扩展以及使用自定义构建系统构建的原生库的作者应当确保展开链完整无缺。 这通常可通过将 -fno-omit-frame-pointer 及类似的旗标添加到 CFLAGS 来实现。 有关 Python 所使用的具体旗标请参阅 --without-frame-pointers 文档。

    (由 Pablo Galindo Salgado 和 Savannah Ostrowski 在 gh-149201 中贡献。).)

  • 使用 Visual Studio 2026 (MSVC 18) 的 64 位构建版现在可以使用新的 尾调用型解释器。 报告 AMD Ryzen 7 5800X 机器的 Windows x86-64 系统上 pyperformance 的几何平均计算在 Visual Studio 18.1.1 中相比 switch-case 型解释器提速的几何平均值在 15-20% 之间。 我们观察到在 Windows 上的提速幅度从大型纯 Python 库的 14% 到长期运行的小型纯 Python 脚本的 40% 不等。 这一成绩是通过在 MSVC 18 中引入的新特性实现的,现在已被 python.org 上的官方 Windows 64 位二进制版所使用。 (由 Chris Eibl, Ken Jin 和 Brandt Bucher 在 gh-143068 中贡献。 特别致谢 Steve Dower 和 MSVC 团队包括 Hulon Jenkins。)

移植到 Python 3.15

本节列出了先前描述的更改以及可能需要更改代码的其他错误修正。