Python 3.13 有什么新变化
- 编者:
- Adam Turner 和 Thomas Wouters
本文介绍了 Python 3.13 相比 3.12 增加的新特性。 Python 3.13 已于 2024 年 10 月 7 日发布。 要获取详细信息,可参阅 更新日志。
参见
PEP 719 [https://peps.python.org/pep-0719/] — Python 3.13 发布计划
摘要 — 发布重点
Python 3.13 是 Python 编程语言的最新稳定发布版,包含多项针对语言、实现和标准库的改变。 最大的变化包括一个新的 交互式解释器,以及对于在 自由线程模式 ( PEP 703 [https://peps.python.org/pep-0703/]) 下运行和 即时编译器 ( PEP 744 [https://peps.python.org/pep-0744/]) 的实验性支持。
错误消息继续得到改进,回溯信息现在默认使用彩色高亮显示。 locals()
内置函数现在对于修改所返回的映射具有 更细化的语法,并且类型形参现在支持设置默认值。
针对标准库的改变包括移除已弃用的 API 和模块,以及用户友好度和正确性方面的常规提升。 一些旧式标准库模块自 Python 3.11 起被弃用 ( PEP 594 [https://peps.python.org/pep-0594/]) 之后现在 已被移除。
本文并不试图提供所有新特性的完整规范说明,而是提供一个方便的概览。 要了解完整细节请参阅相应文档,如 标准库参数 和 语言参考。 要了解某项改变的完整实现和设计理念,请参阅相应新特性的 PEP;但请注意一旦某项特性已完全实现则相应 PEP 通常不会再继续更新。 请参阅 迁移到 Python 3.13 了解如何从较早 Python 进行升级的指导。
解释器的改进:
PEP 667 [https://peps.python.org/pep-0667/]: 现在
locals()
内置函数在修改被返回的映射时具有 已定义语义。 Python 调试器及类似的工具现在即使在并发代码执行期间也能更可靠地在已优化的作用域中更新局部变量。PEP 703 [https://peps.python.org/pep-0703/]: CPython 3.13 具有对在运行时禁用 global interpreter lock 的实验性支持。 请参阅 自由线程 CPython 了解详情。
PEP 744 [https://peps.python.org/pep-0744/]: 增加了一个基本的 JIT 编译器。 目前默认是禁用的(但以后可能启用)。 能够小幅提升性能 — 我们预计在接下来的几个发布版中不断改进它。
在新的 交互式解释器 中,以及 回溯信息 和 文档测试 输出中的颜色支持。 这可以通过
PYTHON_COLORS
andNO_COLOR
[https://no-color.org/] 环境变量来禁用。
对 Python 数据模型的改进:
__static_attributes__
保存了可在一个类体的任何函数中通过self.X
来访问的属性名称。__firstlineno__
记录了一个类定义的首行的行号。
标准库中的重大改进:
新增了
PythonFinalizationError
异常,当操作在 最终化 期间被阻塞时将被引发。现在
argparse
模块可支持弃用命令行选项、位置参数和子命令。新增的函数
base64.z85encode()
和base64.z85decode()
支持对 Z85 数据 [https://rfc.zeromq.org/spec/32/] 进行编码和解码。现在
copy
模块有一个copy.replace()
函数,支持许多内置类型和任何定义了__replace__()
方法的类。新的
dbm.sqlite3
模块现在是默认的dbm
后端。
安全改进:
C API 的改进:
现在
Py_mod_gil
槽位被用来指明一个扩展模块支持在禁用 GIL 的情况下运行。增加了 PyTime C API,提供了对系统时钟的访问。
PyMutex
是新增的轻量级互斥锁,只占用一个字节。新增了 一套函数 用于在 C API 中生成 PEP 669 [https://peps.python.org/pep-0669/] 监控事件。
新的类型标注特性:
PEP 696 [https://peps.python.org/pep-0696/]: 类型形参 (
typing.TypeVar
,typing.ParamSpec
和typing.TypeVarTuple
) 现在可支持默认值。PEP 702 [https://peps.python.org/pep-0702/]: 新的
warnings.deprecated()
装饰器在类型系统和运行时中增加了对标记为弃用的支持。PEP 705 [https://peps.python.org/pep-0705/]:
typing.ReadOnly
可被用来将typing.TypedDict
的项标记为对类型检查器只读。PEP 742 [https://peps.python.org/pep-0742/]:
typing.TypeIs
提供了更直观的类型细化行为,作为对typing.TypeGuard
的替代。
平台支持:
PEP 730 [https://peps.python.org/pep-0730/]: 现在 Apple 的 iOS 是 官方支持的平台,处于 第 3 层级 [https://peps.python.org/pep-0011/#tier-3]。
PEP 738 [https://peps.python.org/pep-0738/]: 现在 Android 是 官方支持的平台,处于 第 3 层级 [https://peps.python.org/pep-0011/#tier-3]。
现在
wasm32-wasi
作为 第 2 层级 [https://peps.python.org/pep-0011/#tier-2] 的平台受到支持。wasm32-emscripten
不再是受到官方支持的平台。
重要的移除:
PEP 594: 剩余的 19 个“死电池”(老旧 stdlib 模块)已从标准库中移除:
aifc
,audioop
,cgi
,cgitb
,chunk
,crypt
,imghdr
,mailcap
,msilib
,nis
,nntplib
,ossaudiodev
,pipes
,sndhdr
,spwd
,sunau
,telnetlib
,uu
和xdrlib
。移除了 2to3 工具和
lib2to3
模块(在 Python 3.11 中已被弃用)。移除了
tkinter.tix
模块(在 Python 3.6 中已被弃用)。移除了
locale.resetlocale()
函数。移除了
typing.io
和typing.re
命名空间。移除了链式的
classmethod
描述器。
发布计划的变化:
PEP 602 [https://peps.python.org/pep-0602/] ("Annual Release Cycle for Python") 已被更新为将新发布版的完整支持 ('bugfix') 期扩展至两年。 这个更新的政策意味着:
Python 3.9—3.12 有一年半的完整支持,另加三年半的安全修正。
Python 3.13 及以后的版本有两年的完整支持,另加三年的安全修正。
新的特性
更好的交互式解释器
Python 现在默认会使用新的 interactive shell,它基于来自 PyPy 项目 [https://pypy.org/] 的代码。 当使用从交互式终端启动 REPL 时,下列新特性将受到支持:
多行编辑并保留历史记录。
对 REPL 专属的命令如 help, exit 和 quit 的直接支持,无需以函数形式调用它们。
提示和回溯 默认启用彩色显示。
使用 F1 浏览交互式帮助并带有单独的命令历史。
使用 F3 进入“粘贴模式”以更方便地粘贴大段代码(再次按 F3 返回常规提示符)。
要禁用新的交互式 shell,可设置 PYTHON_BASIC_REPL
环境变量。 有关交互模式的详情,请参见 交互模式。
(由 Pablo Galindo Salgado, Łukasz Langa 和 Lysandros Nikolaou 在 gh-111201 [https://github.com/python/cpython/issues/111201] 基于来自 PyPy 项目的代码贡献。 Windows 支持由 Dino Viehland 和 Anthony Shaw 贡献。)
改进的错误消息
- 在终端里显示回溯时解释器现在会默认使用彩色。 此特性可通过新的
PYTHON_COLORS
环境变量以及传统的NO_COLOR
[https://no-color.org/] 和FORCE_COLOR
[https://force-color.org/] 环境变量来 进行控制。 (由 Pablo Galindo Salgado 在 gh-112730 [https://github.com/python/cpython/issues/112730] 中贡献。)
- 一个常见错误是撰写的脚本和标准库中的某个模块重名。现在出现此类错误时会显示一条更有用的错误信息:
- $ python random.py
- Traceback (most recent call last):
- File "homeme/random.py", line 1, in <module> import random
- File "homeme/random.py", line 3, in <module> print(random.randint(5)) ^^^^^^^^^^^^^^
- AttributeError: module 'random' has no attribute 'randint' (consider renaming 'homeme/random.py' since it has the same name as the standard library module named 'random' and prevents importing that standard library module)
类似地,如果一个脚本具有与它尝试导入的第三方模块相同的名称并因此导致错误,我们也会显示一条更有帮助的错误消息:
- $ python numpy.py
- Traceback (most recent call last):
- File "homeme/numpy.py", line 1, in <module> import numpy as np
- File "homeme/numpy.py", line 3, in <module> np.array([1, 2, 3]) ^^^^^^^^
- AttributeError: module 'numpy' has no attribute 'array' (consider renaming 'homeme/numpy.py' if it has the same name as a library you intended to import)
(由 Shantanu Jain 在 gh-95754 [https://github.com/python/cpython/issues/95754] 中贡献)。
- 现在当向一个函数传入不正确的关键字参数时错误消息会尝试提示正确的关键字参数。
- >>> "Better error messages!".split(max_split=1)
- Traceback (most recent call last):
- File "<python-input-0>", line 1, in <module> "Better error messages!".split(max_split=1) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^
- TypeError: split() got an unexpected keyword argument 'max_split'. Did you mean 'maxsplit'?
(由 Pablo Galindo Salgado 和 Shantanu Jain 在 gh-107944 [https://github.com/python/cpython/issues/107944] 中贡献。)
自由线程的 CPython
现在 CPython 具有对运行于禁用 global interpreter lock (GIL) 的自由线程模式的实验性支持。 这是一个实验性的特性因而默认是不启用的。 自由线程模式需要一个不同的可执行程序,通常名为 python3.13t
或 python3.13t.exe
。 标记为 freethreaded 的预构建二进制文件可作为官方 Windows 和 macOS 安装器的一部分被安装,或者可以附带 --disable-gil
选项使用源代码来构建 CPython。
自由线程模式的执行允许在可用的 CPU 核心上并行地运行线程从而充分利用可用的处理能力。 虽然并非所有软件都能自动从中受益,但在设计时将线程纳入考虑的程序在多核心硬件上运行速度会更快。 自由线程模式是实验性的 并且处于不断改进的过程中:预计会出现一些程序错误并且在单线程场景下出现明显的性能损失。 可以选择使用环境变量 PYTHON_GIL
或命令行选项 -X gil=1
让 CPython 的自由线程构建版支持在运行时启用 GIL。
要判断当前解释器是否支持自由线程,可检查 python -VV
和 sys.version
是否包含 "experimental freethreading build"。 新的 sys.isgil_enabled()
函数可用于检查在运行进程中 GIL 是否确实被关闭。
C-API 扩展模块需要针对自由线程构建版专门进行构建。 支持在禁用 GIL 的情况下运行的扩展应当使用 Py_mod_gil
槽位。 使用单阶段初始化的扩展应当使用 PyUnstable_Module_SetGIL()
来指明它们是支支持在禁用 GIL 的情况下运行。 导入不使用这些机制的 C 扩展将导致 GIL 被启用,除非通过 PYTHON_GIL
环境变量或 -X gil=0
选项显式地禁用 GIL。 需要 pip 24.1 或更新的版本才能在自由线程构建版中安装带有 C 扩展的软件包。
这项工作成为可能要感谢许多个人和组织,包括针对 Python 和第三方项目测试并启用自由线程支持的庞大的贡献者社区。 重要的贡献者包括:Sam Gross, Ken Jin, Donghee Na, Itamar Oren, Matt Page, Brett Simmers, Dino Viehland, Carl Meyer, Nathan Goldbaum, Ralf Gommers, Lysandros Nikolaou 及其他许多人。 有许多贡献者受雇于 Meta,该公司提供了大量的工程资源来支持此项目。
参见
PEP 703 [https://peps.python.org/pep-0703/] "Making the Global Interpreter Lock Optional in CPython" 中包含了有关此项工作的理念和信息。
Porting Extension Modules to Support FreeThreading [https://py-free-threading.github.io/porting/]: 一份由社区维护的针对扩展开发者的移植指南。
实验性的即时 (JIT) 编译器
当 CPython 使用 --enable-experimental-jit
选项进行配置和构建时,会添加一个即时(JIT)编译器以加快某些 Python 程序的运行速度。 在 Windows 上,可使用 PCbuild/build.bat --experimental-jit
启用 JIT 或使用 --experimental-jit-interpreter
启用第 2 层级解释器。 构建要求和进一步的支持信息 包含在 [https://github.com/python/cpython/blob/main/Tools/jit/README.md] Tools/jit/README.md
中。
--enable-experimental-jit
选项接受这些(可选)值,如果不带可选值地预设 --enable-experimental-jit
则默认为 yes
。
no
: 禁用整个第 2 层级和 JIT 管线。yes
: 启用 JIT。 要在运行时禁用 JIT,则传入环境变量PYTHON_JIT=0
。yes-off
: 构建 JIT 但默认禁用它。 要在运行时启用 JIT,则传入环境变量PYTHON_JIT=1
。interpreter
: 启用第 2 层级解释器但是禁用 JIT。 可以在运行时传入PYTHON_JIT=0
来禁用该解释器。
其内部架构大致如下:
我们将从特化的 第 1 层级字节码 开始。 请参阅 3.11 有什么新变化 了解详情。
当第 1 层级字节码达到足够热度,它将被翻译为新的纯内部的中间表示形式 (IR),称为 第 2 层级 IR,有时也称为微操作码 ("uops")。
第 2 层级 IR 使用与第 1 层级相同的基于栈的虚拟机,但其指令格式更适合被翻译为机器码。
在第 2 层级 IR 被解释或翻译为机器码之前,我们会预先应用一些优化通路。
虽然第 2 层级解释器存在,但它主要用于对优化管线的先前阶段进行调试。可通过为 Python 配置
--enable-experimental-jit=interpreter
选项启用第 2 层级解释器。启用 JIT 时,经优化的第 2 层级 IR 将被翻译为机器码后再执行。
这个机器码翻译过程使用了名为 拷贝并打补丁 的技巧。 它没有运行时依赖,但增加了构建时对 LLVM 的依赖。
参见
PEP 744 [https://peps.python.org/pep-0744/]
(JIT 来自 Brandt Bucher 且受到 Haoran Xu 和 Fredrik Kjolstad 论文的启发。第 2 层级 IR 来自 Mark Shannon 和 Guido van Rossum。第 2 层级解释器来自 Ken Jin。)
针对 locals()
的已定义修改语义
在历史上,改变 locals()
的返回值的预期结果是留给具体的 Python 实现来定义的。 从 Python 3.13 开始, PEP 667 [https://peps.python.org/pep-0667/] 标准化了 CPython 对于大多数代码执行作用域的历史行为,但也将 已优化作用域 (函数、生成器、协程、推导式和生成器表达式) 修改为显式地返回当前已赋值的局部变量的独立快照,包括局部引用的在闭包中捕获的非局部变量。
在已优化作用域中对 locals()
语义的这项修改也会影响隐式地以 locals()
为目标的代码执行函数的默认行为,如果没有提供显式命名空间的话(例如 exec()
和 eval()
等)。 在之前的版本中,在调用代码执行函数后是否可以通过调用 locals()
访问更改情况取决于具体的实现。 具体到 CPython 而言,此类代码通常会按预期工作,但有时可能会在基于其他代码(包括调试器和代码执行跟踪工具)的已优化作用域中失败,因为代码有可能重置该作用域中的共享快照。 现在,代码在已优化作用域中将始终针对局部变量的独立快照运行,因为在后续调用 locals()
时将永远看不到更改。 要访问在这些情况下所做的更改,现在必须将一个显式命名空间引用传递给相关的函数。 或者,也可以更新受影响的代码以使用更高层级的代码执行 API 返回结果代码命名空间(例如,当执行磁盘上的 Python 文件时使用 runpy.run_path()
函数)。
为确保调试器和类似工具能可靠地更新受到此变化影响的作用域中的局部变量,现在 FrameType.f_locals
将返回一个针对此种作用域中的帧的局部变量和在局部引用的非局部变量的直通写入代理对象,而不是返回一个非持续更新的具有规定义的运行时语义的共享 dict
实例。
请参阅 PEP 667 [https://peps.python.org/pep-0667/] 了解详情,包括相关的 C API 更改和弃用。 下文还针对受影响的 Python API 和 C API 提供了移植说明。
(PEP 和实现由 Mark Shannon 和 Tian Gao 在 gh-74929 [https://github.com/python/cpython/issues/74929] 中贡献。 文档更新由 Guido van Rossum 和 Alyssa Coghlan 提供。)
对移动平台的支持
PEP 730 [https://peps.python.org/pep-0730/]: iOS 现在是 PEP 11 [https://peps.python.org/pep-0011/] 所支持的平台,包括第 3 层级的 arm64-apple-ios
和 arm64-apple-ios-simulator
等目标(分别为2013 年后的 iPhone 和 iPad 设备以及运行于 Apple silicon 硬件的 Xcode iOS 模拟器)。 x86_64-apple-ios-simulator
(运行于较旧的 x86_64
硬件的 Xcode iOS 模拟器)不是第 3 层级的受支持平台,但也将尽可能地支持。 (PEP 撰写及实现由 Russell Keith-Magee 在 gh-114099 [https://github.com/python/cpython/issues/114099] 中贡献。).) PEP 738 [https://peps.python.org/pep-0738/]: Android 现在是 PEP 11 [https://peps.python.org/pep-0011/] 所支持的平台,包括位于第 3 层级的 aarch64-linux-android
和 x86_64-linux-android
等目标。 32 位的目标 arm-linux-androideabi
和 i686-linux-android
不是第 3 层级的受支持平台,但也将尽可能地支持。 (PEP 撰写及实现由 Malcolm Smith 在 gh-116622 [https://github.com/python/cpython/issues/116622] 中贡献。)
参见
PEP 730 [https://peps.python.org/pep-0730/], PEP 738 [https://peps.python.org/pep-0738/]
其他语言特性修改
- 编译器现在将从文档字符串的每一行去除共有的前导空格。 这会减少 字节码缓存 的大小(例如
.pyc
文件),例如在 SQLAlchemy 2.0 的sqlalchemy.orm.session
中文件大小将减少约 5%。 这项改变将影响各种使用了文档字符串的工具,如doctest
。
- >>> def spam():
- ... """
- ... This is a docstring with
- ... leading whitespace.
- ...
- ... It even has multiple paragraphs!
- ... """
- ...
- >>> spam.__doc__
- '\nThis is a docstring with\n leading whitespace.\n\nIt even has multiple paragraphs!\n'
(由 Inada Naoki 在 gh-81283 [https://github.com/python/cpython/issues/81283] 中贡献。)
- 类作用域内的 标注作用域 现在可以包含 lambda 和推导式。 位于类作用域内的推导式不会内联到其父作用域中。
- class C[T]:
- type Alias = lambda: T
(由 Jelle Zijlstra 在 gh-109118 [https://github.com/python/cpython/issues/109118] 和 gh-118160 [https://github.com/python/cpython/issues/118160] 中贡献。)
future 语句 不再会被
__future__
模块的相对导入触发,意味着from .__future__ import …
形式的语句现在只是标准的相对导入,而不会激活任何特殊特性。 (由 Jeremiah Gabriel Pascual 在 gh-118216 [https://github.com/python/cpython/issues/118216] 中贡献。)现在
global
声明当其被用于else
代码块中时也将被允许在except
代码块中使用。 在之前版本中这会错误地引发SyntaxError
。 (由 Irit Katriel 在 gh-111123 [https://github.com/python/cpython/issues/111123] 中贡献。)增加了新的环境变量
PYTHON_FROZEN_MODULES
,它确定冻结模块是否会被导入机制所忽略,等价于-X frozen_modules
命令行选项。 (由 Yilei Yang 在 gh-111374 [https://github.com/python/cpython/issues/111374] 中贡献。)通过新的环境变量
PYTHON_PERF_JIT_SUPPORT
和命令行选项-X perf_jit
添加无需 帧指针 [https://en.wikipedia.org/wiki/Call_stack] 即可工作的 对 perf 性能分析器的支持。 (由 Pablo Galindo 在 gh-118518 [https://github.com/python/cpython/issues/118518] 中贡献。)可通过新的
PYTHON_HISTORY
环境变量来更改.python_history
文件的位置。 (由 Levi Sabah, Zackery Spytz 和 Hugo van Kemenade 在 gh-73965 [https://github.com/python/cpython/issues/73965] 中贡献。)类新增了一个
__static_attributes__
属性。 这由编译器以类属性名称的元组来填充,这些名称是从类体中的任何函数通过self.
来赋值的。 (由 Irit Katriel 在 gh-115775 [https://github.com/python/cpython/issues/115775] 中贡献。).)编译器现在会在类上创建一个
__firstlineno__
属性,其值为类定义第一行的行号。 (由 Serhiy Storchaka 在 gh-118465 [https://github.com/python/cpython/issues/118465] 中贡献。)现在
exec()
和eval()
内置函数接受以关键字形式传入的 globals 和 locals 参数。 (由 Raphael Gaschignard 在 gh-105879 [https://github.com/python/cpython/issues/105879] 中贡献。)现在
compile()
内置函数接受一个新的旗标ast.PyCF_OPTIMIZED_AST
,它类似于ast.PyCF_ONLY_AST
但区别在于返回的 AST 是根据 optimize 参数的值进行优化的。 (由 Irit Katriel 在 gh-108113 [https://github.com/python/cpython/issues/108113] 中贡献。)在
property
对象上增加了__name__
属性。 (由 Eugene Toder 在 gh-101860 [https://github.com/python/cpython/issues/101860] 中贡献。)增加了新的异常
PythonFinalizationError
,它派生自RuntimeError
,用于当操作在 最终化 期间被阻塞时发出信号。 下列可调用对象现在将引发PythonFinalizationError
,而不是RuntimeError
:
(由 Victor Stinner 在 gh-114570 [https://github.com/python/cpython/issues/114570] 中贡献。)
允许
str.replace()
的 count 参数为关键字参数。 (由 Hugo van Kemenade 在 gh-106487 [https://github.com/python/cpython/issues/106487] 中贡献。)现在许多函数会对将布尔值作为文件描述符参数发出警告。这可以帮助尽早发现一些错误。(由 Serhiy Storchaka 在 gh-82626 [https://github.com/python/cpython/issues/82626] 中贡献。)
为
bz2
,lzma
,tarfile
和zipfile
等模块中的已压缩和已归档文件型对象添加了name
和mode
属性。 (由 Serhiy Storchaka 在 gh-115961 [https://github.com/python/cpython/issues/115961] 中贡献。)
新增模块
dbm.sqlite3
: 针对dbm
的 SQLite 后端。 (由 Raymond Hettinger 和 Erlend E. Aasland 在 gh-100414 [https://github.com/python/cpython/issues/100414] 中贡献。)
改进的模块
argparse
- 为
add_argument()
和add_parser()
方法添加了 deprecated 形参,以允许弃用命令行选项、位置参数和子命令。 (由 Serhiy Storchaka 在 gh-83648 [https://github.com/python/cpython/issues/83648] 中贡献。)
array
增加了
'w'
类型码 (Py_UCS4
) 表示 Unicode 字符。 它应被用来代替已弃用的'u'
类型码。 (由 Inada Naoki 在 gh-80480 [https://github.com/python/cpython/issues/80480] 中贡献。)通过实现
clear()
方法将array.array
注册为MutableSequence
。 (由 Mike Zimin 在 gh-114894 [https://github.com/python/cpython/issues/114894] 中贡献。)
ast
- 现在
ast
模块中节点类型的构造器对其接受的参数要求更为严格,并在参数被省略时有更易理解的行为。
如果在构造实例时某个 AST 节点上的可选字段没有被作为参数包括在内,则该字段现在将被设为 None
。 类似地,如果某个列表字段被省略,则该字段现在将被设为空列表,而如果某个 expr_context
字段被省略,则它将默认为 Load()
。 (之前,在所有情况下,新构造的 AST 节点实例上的相应属性都将缺失。)
在所有其他情况下,当需要的参数被省略时,节点构造器将发出 DeprecationWarning
。 这在 Python 3.15 中将会引发异常。 类似地,将关键字参数传入一个未映射到 AST 节点上的字段的构造器的做法现在已被弃用,并且在 Python 3.15 中将会引发异常。
这些更改将不会应用于用户自定义的 ast.AST
子类,除非该类选择通过设置 AST._field_types
映射的方式加入新的行为。
(由 Jelle Zijlstra 在 gh-105858 [https://github.com/python/cpython/issues/105858], gh-117486 [https://github.com/python/cpython/issues/117486] 和 gh-118851 [https://github.com/python/cpython/issues/118851] 中贡献。)
- 现在
ast.parse()
接受一个可选参数 optimize,它会被传递给compile()
。 这使得获取已优化的 AST 成为可能。 (由 Irit Katriel 在 gh-108113 [https://github.com/python/cpython/issues/108113] 中贡献。)
asyncio
现在
asyncio.as_completed()
将返回一个即是 asynchronous iterator 又是基本的产生 可等待对象 的 iterator 的对象。 由异常迭代产生的可等待对象包括被传入的原始 Task 或 Future 对象,使得将结果与正在完成的任务相关联更为容易。 (由 Justin Arthur 在 gh-77714 [https://github.com/python/cpython/issues/77714] 中贡献。)现在当服务器被关闭时
asyncio.loop.create_unix_server()
会自动移除 Unix 套接字。 (由 Pierre Ossman 在 gh-111246 [https://github.com/python/cpython/issues/111246] 中贡献。)现在当附带一个空字节串对象调用时
DatagramTransport.sendto()
将发送零长度的数据报。 现在当计算缓冲区大小时传输控制流还会将数据报标头纳入考量。 (由 Jamie Phan 在 gh-115199 [https://github.com/python/cpython/issues/115199] 中贡献。)增加了
Queue.shutdown
和QueueShutDown
用于管理队列终结。 (由 Laurie Opperman 和 Yves Duprat 在 gh-104228 [https://github.com/python/cpython/issues/104228] 中贡献。)增加了
Server.close_clients()
和Server.abort_clients()
方法,它们会以更强制的方式关闭 asyncio 服务器。 (由 Pierre Ossman 在 gh-113538 [https://github.com/python/cpython/issues/113538] 中贡献。)在
StreamReader.readuntil()
中接受一个由分隔符组成的元组,当遇到其中之一时就会停止。 (由 Bruce Merry 在 gh-81322 [https://github.com/python/cpython/issues/81322] 中贡献。)改进了
TaskGroup
在外部的取消操作与内部的取消操作发生冲突时的行为。 例如,当嵌套两个任务分组并且两者同时在某个子任务中遇到异常时,外层的任务分组有可能被挂起,因为其内部的取消操作已由内层的任务分组进行处理。
对于任务分组在外部被取消时同时必须引发 ExceptionGroup
的情况,现在它将调用父任务的 cancel()
方法。 这样可以确保 CancelledError
会在下一次 await
时被引发,因此取消操作不会丢失。, so the cancellation is not lost.
这些更改的一个附加好处是现在任务组会保留取消操作计数 (cancelling()
)。
为了处理某些边界情况,现在 uncancel()
可以在取消操作计数达到零时重置未写入文档的 mustcancel
旗标。
(受到由 Arthur Tacca 在 gh-116720 [https://github.com/python/cpython/issues/116720] 中报告的问题的启发。)
- 当在一个未激活的
TaskGroup
上调用TaskGroup.create_task()
时,给定的协程将被关闭 (这将防止引发有关给定的协程从未被等待的RuntimeWarning
)。 (由 Arthur Tacca 和 Jason Zhang 在 gh-115957 [https://github.com/python/cpython/issues/115957] 中贡献。)
base64
- 增加了
z85encode()
和z85decode()
函数用于将bytes
编码为 Z85 data [https://rfc.zeromq.org/spec/32/] 和将 Z85 编码的数据解码为bytes
。 (由 Matan Perelman 在 gh-75299 [https://github.com/python/cpython/issues/75299] 中贡献。)
compileall
- 工作线程和进程的默认数据现在是使用
os.process_cpu_count()
而不是os.cpu_count()
来选择的。 (由 Victor Stinner 在 gh-109649 [https://github.com/python/cpython/issues/109649] 中贡献。)
concurrent.futures
- 工作线程和进程的默认数据现在是使用
os.process_cpu_count()
而不是os.cpu_count()
来选择的。 (由 Victor Stinner 在 gh-109649 [https://github.com/python/cpython/issues/109649] 中贡献。)
configparser
- 现在
ConfigParser
具有对未命名节的支持,这将允许使用最高层级的键值对。 此特性可通过新增的 allow_unnamed_section 形参来启用。 (由 Pedro Sousa Lacerda 在 gh-66449 [https://github.com/python/cpython/issues/66449] 中贡献。)
copy
新增的
replace()
函数和replace 协议
使得创建经修改的对象副本更为简单。 这在操作不可变对象时特别有用。 以下类型将支持replace()
函数并实现了 replace 协议:
任何用户自定义类也可以通过定义 __replace__()
方法来支持 copy.replace()
。 (由 Serhiy Storchaka 在 gh-108751 [https://github.com/python/cpython/issues/108751] 中贡献。)
ctypes
作为必要的内部重构的一个后果,内部元类的初始化现在将发生于
__init__
中而不是__new__
中。 这会影响子类化这些内部元类以提供自定义初始化的项目。 一般而言:调用
super().__new__
之后在__new__
中完成的自定义逻辑应当移至__init__
。要创建一个类,需调用相应的元类,而不仅是该元类的
__new__
方法。
请参阅 gh-124520 [https://github.com/python/cpython/issues/124520] 了解相关讨论和对某些受影响项目的修改的链接。
ctypes.Structure
对象新增了一个align
属性以允许显式地指定发往内存的结构体对齐方式。 (由 Matt Sanderson 在 gh-112433 [https://github.com/python/cpython/issues/112433] 中贡献。)
dbm
增加
dbm.sqlite3
,一个实现了 SQLite 后端的新模块,并将其设为默认的dbm
后端。 (由 Raymond Hettinger 和 Erlend E. Aasland 在 gh-100414 [https://github.com/python/cpython/issues/100414] 中贡献。)允许通过新增的
gdbm.clear()
和ndbm.clear()
方法移除数据库中的所有条目。 (由 Donghee Na 在 gh-107122 [https://github.com/python/cpython/issues/107122] 中贡献。)
dis
将
dis
模块的函数的输出修改为显示跳转目标和异常处理器的逻辑标签,而不是偏移量。 可以使用新的-O
命令行选项或 show_offsets 参数来添加偏移量。 (由 Irit Katriel 在 gh-112137 [https://github.com/python/cpython/issues/112137] 中贡献。)get_instructions()
不再将缓存条目表示为单独的指令。 作为替代,它会将它们作为Instruction
的组成部分返回,放在新的 cache_info 字段中。 传给get_instructions()
的 show_caches 参数已被弃用并且不再有任何效果。 (由 Irit Katriel 在 gh-112962 [https://github.com/python/cpython/issues/112962] 中贡献。)
doctest
现在
doctest
输出默认是彩色的。 此特性可通过新增的PYTHON_COLORS
环境变量和传统的NO_COLOR
[https://no-color.org/] 和FORCE_COLOR
[https://force-color.org/] 环境变量来控制。 另请参阅 控制颜色。 (由 Hugo van Kemenade 在 gh-117225 [https://github.com/python/cpython/issues/117225] 中贡献。)现在
DocTestRunner.run()
方法会统计已跳过测试的数量。 增加了DocTestRunner.skips
和TestResults.skipped
属性。 (由 Victor Stinner 在 gh-108794 [https://github.com/python/cpython/issues/108794] 中贡献。)
现在带有嵌入的换行符的标头在输出时会加上引号。 现在
generator
会拒绝序列化(写入)不正确地折叠或分隔的标头,例如将被解析为多个标头或与相邻数据合并的标头等。 如果你需要禁用此安全特性,请设置verify_generated_headers
。 (由 Bas Bloemsaat 和 Petr Viktorin 在 gh-121650 [https://github.com/python/cpython/issues/121650] 中贡献。)现在
getaddresses()
和parseaddr()
会在更多遇到无效 email 地址的情况下返回('', '')
对非可能不准确的值。 这两个函数新增了可选的 strict 形参 (默认为True
)。 要获取旧版本的行为 (接受错误格式的输入),请使用strict=False
。getattr(email.utils, 'supports_strict_parsing', False)
可被用于检查 strict 形参是否可用。 (由 Thomas Dwyer 和 Victor Stinner 针对 gh-102988 [https://github.com/python/cpython/issues/102988] 贡献以改进 CVE 2023-27043 [https://www.cve.org/CVERecord?id=CVE-2023-27043] 修正。)
enum
fractions
- 现在
Fraction
对象支持用于填充、对齐、正负号处理、最小宽度和分组的标准 格式说明迷你语言 规则。 (由 Mark Dickinson 在 gh-111320 [https://github.com/python/cpython/issues/111320] 中贡献。)
glob
- 增加了
translate()
,这是个用来将具有 shell 风格通配符的路径说明转换为正则表达式的函数。 (由 Barney Gale 在 gh-72904 [https://github.com/python/cpython/issues/72904] 中贡献。)
importlib
现在
importlib.resources
中的下列函数允许访问资源目录(或树),并使用多个位置参数(现在文本读取函数中的 encoding 和 errors 参数是仅限关键字参数):
这些函数将不再被弃用也不会被加入移除计划。 (由 Petr Viktorin 在 gh-116608 [https://github.com/python/cpython/issues/116608] 中贡献。)
contents()
仍然被弃用而应改用功能完整的Traversable
API。 不过,目前还没有移除它的计划。 (由 Petr Viktorin 在 gh-116608 [https://github.com/python/cpython/issues/116608] 中贡献。)
io
- 现在
IOBase
最终化器会使用sys.unraisablehook
来将由close()
方法引发的错误写入日志。 在之前版本中,错误在默认情况下会被静默地忽略,而只有在 Python 开发模式 或在使用 Python 调试构建版 时才会被写入日志。 (由 Victor Stinner 在 gh-62948 [https://github.com/python/cpython/issues/62948] 中贡献。)
ipaddress
增加了
IPv4Address.ipv6_mapped
特征属性,它将返回映射 IPv4 的 IPv6 地址。 (由 Charles Machalow 在 gh-109466 [https://github.com/python/cpython/issues/109466] 中贡献。)修正了
IPv4Address
,IPv6Address
,IPv4Network
和IPv6Network
中is_global
和is_private
的行为。 (由 Jakub Stasiak 在 gh-113171 [https://github.com/python/cpython/issues/113171] 中贡献。)
itertools
batched()
新增了 strict 形参,它会在最后一批次数据小于指定批准大小时引发ValueError
。 (由 Raymond Hettinger 在 gh-113202 [https://github.com/python/cpython/issues/113202] 中贡献。)
marshal
- 在模块函数中增加了 allow_code 形参。 传入
allow_code=False
将防止在 Python 各版本间不兼容的代码对象的序列化和反序列化。 (由 Serhiy Storchaka 在 gh-113626 [https://github.com/python/cpython/issues/113626] 中贡献。)
math
- 新增函数
fma()
可执行合并的乘法-加法运算。 此函数只需一轮操作即可计算x * y + z
,从而避免了任何中间步骤导致的精度损失。 它包装了 C99 所提供的fma()
函数,并且遵从针对特殊情况的 IEEE 754 "fusedMultiplyAdd" 运算规范。 (由 Mark Dickinson 和 Victor Stinner 在 gh-73468 [https://github.com/python/cpython/issues/73468] 中贡献。)
mimetypes
- 增加了
guess_file_type()
函数用于根据文件系统路径来猜测 MIME 类型。 在guess_type()
中使用路径的做法现在已是 soft deprecated。 (由 Serhiy Storchaka 在 gh-66543 [https://github.com/python/cpython/issues/66543] 中贡献。)
mmap
现在
mmap
在 Windows 上当被映射的内存由于文件系统错误或访问限制而不可访问时将获得保护以避免崩溃。 (由 Jannis Weigend 在 gh-118209 [https://github.com/python/cpython/issues/118209] 中贡献。)mmap
具有新的seekable()
方法将在需要可定位的文件型对象时被使用。 现在seek()
方法将返回一个新的绝对位置。 (由 Donghee Na 和 Sylvie Liberman 在 gh-111835 [https://github.com/python/cpython/issues/111835] 中贡献。)mmap
新增了 UNIX 专属的 trackfd 形参用来控制文件描述符的复制;如为假值,则由 fileno 指定的文件描述符将不会被复制。 (由 Zackery Spytz 和 Petr Viktorin 在 gh-78502 [https://github.com/python/cpython/issues/78502] 中贡献。)
multiprocessing
- 工作线程和进程的默认数据现在是使用
os.process_cpu_count()
而不是os.cpu_count()
来选择的。 (由 Victor Stinner 在 gh-109649 [https://github.com/python/cpython/issues/109649] 中贡献。)
os
增加了
process_cpu_count()
函数用于获取当前进程的调用方线程可以使用的逻辑 CPU 核心数量。 (由 Victor Stinner 在 gh-109649 [https://github.com/python/cpython/issues/109649] 中贡献。)cpu_count()
和process_cpu_count()
可通过新的环境变量PYTHON_CPU_COUNT
或新的命令行选项-X cpu_count
来覆盖。 此选项对于需要在不修改应用程序代码或容器本身的情况下限制一个容器系统的 CPU 资源的用户会很有用处。 (由 Donghee Na 在 gh-109595 [https://github.com/python/cpython/issues/109595] 中贡献。)通过
timerfd_create()
,timerfd_settime()
,timerfd_settime_ns()
,timerfd_gettime()
,timerfd_gettime_ns()
,TFD_NONBLOCK
,TFD_CLOEXEC
,TFD_TIMER_ABSTIME
和TFD_TIMER_CANCEL_ON_SET
增加了针对 Linux 的 计算器文件描述符) [https://manpages.debian.org/timerfd_create(2)] 的 低层级接口。 (由 Masaru Tsuchiyama 在 gh-108277 [https://github.com/python/cpython/issues/108277] 中贡献。)在 Windows 上现在同时增加了对
lchmod()
和chmod()
的 follow_symlinks 参数的支持。 请注意在 Windows 上lchmod()
中的 follow_symlinks 的默认值为False
。 (由 Serhiy Storchaka 在 gh-59616 [https://github.com/python/cpython/issues/59616] 中贡献。)在 Windows 上现在同时增加了
fchmod()
和对chmod()
中的文件描述符的支持。 (由 Serhiy Storchaka 在 gh-113191 [https://github.com/python/cpython/issues/113191] 中贡献。)在 Windows 上,
mkdir()
和makedirs()
现在支持传入 mode 值0o700
以对新目录应用访问控制。 这会隐式地影响tempfile.mkdtemp()
并可缓解 CVE 2024-4030 [https://www.cve.org/CVERecord?id=CVE-2024-4030]。 其他的 mode 值仍然会被忽略。 (由 Steve Dower 在 gh-118486 [https://github.com/python/cpython/issues/118486] 中贡献。)现在
posix_spawn()
可接受None
作为 env 参数,这将让新产生的进程使用当前进程的环境。 (由 Jakub Kulik 在 gh-113119 [https://github.com/python/cpython/issues/113119] 中贡献。).)在支持
posix_spawn_file_actions_addclosefrom_np()
的平台上posix_spawn()
现在可以在 file_actions 形参中使用POSIX_SPAWN_CLOSEFROM
属性。 (由 Jakub Kulik 在 gh-113117 [https://github.com/python/cpython/issues/113117] 中贡献。)
os.path
增加了
isreserved()
用于检查一个路径在当前系统中是否为保留路径。 此函数仅在 Windows 上可用。 (由 Barney Gale 在 gh-88569 [https://github.com/python/cpython/issues/88569] 中贡献。)在 Windows 上,
isabs()
将不再把以恰好一个斜杠 (\
或/
) 开头的路径视为绝对路径。 (由 Barney Gale 和 Jon Foster 在 gh-44626 [https://github.com/python/cpython/issues/44626] 中贡献。)现在即使文件不可访问
realpath()
也能够解析 MS-DOS 风格的文件名。 (由 Moonsik Park 在 gh-82367 [https://github.com/python/cpython/issues/82367] 中贡献。)
pathlib
增加了
UnsupportedOperation
,它会在一个路径操作不受支持时代替NotImplementedError
被引发。 (由 Barney Gale 在 gh-89812 [https://github.com/python/cpython/issues/89812] 中贡献。)新增了一个用于根据 'file' URI (
file:///
) 来创建Path
对象的构造器Path.from_uri()
。 (由 Barney Gale 在 gh-107465 [https://github.com/python/cpython/issues/107465] 中贡献。)增加了
PurePath.full_match()
用于匹配带有 shell 风格通配符的路径,包括递归通配符 "**
"。 (由 Barney Gale 在 gh-73435 [https://github.com/python/cpython/issues/73435] 中贡献。)增加了
PurePath.parser
类属性以存储用于低层级路径解析与合并的os.path
实现。 这可以是posixpath
或ntpath
。为
Path.glob()
和rglob()
增加了 recurse_symlinks 仅限关键字参数。 (由 Barney Gale 在 gh-77609 [https://github.com/python/cpython/issues/77609] 中贡献。)现在当给出以 "
**
" 结束的模式时Path.glob()
和rglob()
将返回文件和目录。 在之前版本中,仅会返回目录。 (由 Barney Gale 在 gh-70303 [https://github.com/python/cpython/issues/70303] 中贡献。).)为
Path.is_file
,Path.is_dir
,Path.owner()
和Path.group()
增加了 follow_symlinks 仅限关键字参数。 (由 Barney Gale 在 gh-105793 [https://github.com/python/cpython/issues/105793] 中,以及 Kamil Turek 在 gh-107962 [https://github.com/python/cpython/issues/107962] 中贡献。)
pdb
现在
breakpoint()
和set_trace()
会立即进入调试器而不是在被执行代码的下一行进入。 这一更改可防止当breakpoint()
位于上下文末尾 时调试器在上下文以外被中断。 (由 Tian Gao 在 gh-118579 [https://github.com/python/cpython/issues/118579] 中贡献。)当设置了
sys.flags.safe_path
时sys.path[0]
将不会再被替换为被调试脚本的目录。 (由 Tian Gao 和 Christian Walther 在 gh-111762 [https://github.com/python/cpython/issues/111762] 中贡献。)现在支持将
zipapp
作为调试目标。 (由 Tian Gao 在 gh-118501 [https://github.com/python/cpython/issues/118501] 中贡献。)添加了在
pm()
中进行事后调试期间使用 Pdb 新增的exceptions [exc_number]
命令在串连的异常之间移动的能力。 (由 Matthias Bussonnier 在 gh-106676 [https://github.com/python/cpython/issues/106676] 中贡献。)以一条 pdb 命令打头的表达式和语句现在会被正确地标识并执行。 (由 Tian Gao 在 gh-108464 [https://github.com/python/cpython/issues/108464] 中贡献。)
queue
- 增加了
Queue.shutdown
和ShutDown
用于管理队列的终结。 (由 Laurie Opperman 和 Yves Duprat 在 gh-104750 [https://github.com/python/cpython/issues/104750] 中贡献。)
random
- 增加了一个 命令行接口。 (由 Hugo van Kemenade 在 gh-118131 [https://github.com/python/cpython/issues/118131] 中贡献。)
re
- 将
re.error
重命名为PatternError
以改善准确性。re.error
仍被保留用于向下兼容。
shutil
- 在
chown()
中增加了对 dir_fd 和 follow_symlinks 关键字参数的支持。 (由 Berker Peksag 和 Tahia K 在 gh-62308 [https://github.com/python/cpython/issues/62308] 中贡献。)
site
- 现在
.pth
文件将先使用 UTF-8 来解码,如果 UTF-8 解码失败再使用 locale encoding。 (由 Inada Naoki 在 gh-117802 [https://github.com/python/cpython/issues/117802] 中贡献。)
sqlite3
现在当一个
Connection
对象未被显式地关闭
时将发出ResourceWarning
。 (由 Erlend E. Aasland 在 gh-105539 [https://github.com/python/cpython/issues/105539] 中贡献。)为
Connection.iterdump()
增加了 filter 仅限关键字形参用于过滤要转储的数据库对象。 (由 Mariusz Felisiak 在 gh-91602 [https://github.com/python/cpython/issues/91602] 中贡献。)
ssl
- 现在
create_default_context()
API 将在其默认旗标中包括VERIFY_X509_PARTIAL_CHAIN
和VERIFY_X509_STRICT
。
备注
VERIFY_X509_STRICT
可能会拒绝下层 OpenSSL 实现本来会接受的 RFC 5280 [https://datatracker.ietf.org/doc/html/rfc5280.html] 以前的证书或格式错误的证书。 虽然不建议禁用此功能,但你可以使用以下方式禁用它:
- import ssl
- ctx = ssl.create_default_context()
- ctx.verify_flags &= ~ssl.VERIFY_X509_STRICT
(由 William Woodruff 在 gh-112389 [https://github.com/python/cpython/issues/112389] 贡献。)
statistics
增加了用于核密度估计的
kde()
。 这使得根据固定数量的离散样本估计连续概率密度函数成为可能。 (由 Raymond Hettinger 在 gh-115863 [https://github.com/python/cpython/issues/115863] 中贡献。)增加了
kde_random()
用来从kde()
创建的估计概率密度函数进行取样。 (由 Hettinger 在 gh-115863 [https://github.com/python/cpython/issues/115863] 中贡献。)
subprocess
- 现在
subprocess
模块会在更多场合下使用posix_spawn()
函数。
需要注意的是,当 close_fds 为 True
时(默认值),则将在 C 库提供了 posix_spawn_file_actions_addclosefrom_np()
时使用 posix_spawn()
,这包括近期的 Linux, FreeBSD 和 Solaris 版本。 在 Linux,其性能应当与现有的 Linux vfork()
基础代码类似。
如果你需要强制 subprocess
绝不使用 posix_spawn()
可以将私有的控制节点 subprocess._USE_POSIX_SPAWN
设为 False
。 如果你这样设置的话请在 issue tracker 中报告你的理由和平台相关的细节以便我们能够为大家改进 API 的选择逻辑。 (由 Jakub Kulik 在 gh-113117 [https://github.com/python/cpython/issues/113117] 中贡献。)