Python 3.11 中的新功能¶
- 编辑:
Pablo Galindo Salgado
本文解释了 Python 3.11 相对于 3.10 的新功能。Python 3.11 于 2022 年 10 月 24 日发布。有关完整详细信息,请参阅 更新日志。
摘要 – 发布亮点¶
Python 3.11 比 Python 3.10 快 10-60%。平均而言,我们在标准基准测试套件上测得 1.25 倍的加速。有关详细信息,请参阅 更快的 CPython。
新语法功能
新的内置功能
新的标准库模块
解释器的改进
新的
-P
命令行选项和PYTHONSAFEPATH
环境变量,用于 禁用自动将可能不安全的路径添加到sys.path
新的类型特性
重要的废弃、移除和限制
PEP 594: 许多遗留的标准库模块已被废弃,并将在 Python 3.13 中移除
新功能¶
PEP 657: 追溯中更精细的错误位置¶
现在,在打印追溯时,解释器将指向导致错误的精确表达式,而不仅仅是行。例如
Traceback (most recent call last):
File "distance.py", line 11, in <module>
print(manhattan_distance(p1, p2))
^^^^^^^^^^^^^^^^^^^^^^^^^^
File "distance.py", line 6, in manhattan_distance
return abs(point_1.x - point_2.x) + abs(point_1.y - point_2.y)
^^^^^^^^^
AttributeError: 'NoneType' object has no attribute 'x'
以前的解释器版本只会指向行,使得哪个对象是 None
变得模糊不清。这些增强的错误在处理深度嵌套的 dict
对象和多个函数调用时也很有帮助
Traceback (most recent call last):
File "query.py", line 37, in <module>
magic_arithmetic('foo')
File "query.py", line 18, in magic_arithmetic
return add_counts(x) / 25
^^^^^^^^^^^^^
File "query.py", line 24, in add_counts
return 25 + query_user(user1) + query_user(user2)
^^^^^^^^^^^^^^^^^
File "query.py", line 32, in query_user
return 1 + query_count(db, response['a']['b']['c']['user'], retry=True)
~~~~~~~~~~~~~~~~~~^^^^^
TypeError: 'NoneType' object is not subscriptable
以及复杂的算术表达式
Traceback (most recent call last):
File "calculation.py", line 54, in <module>
result = (x / y / z) * (a / b / c)
~~~~~~^~~
ZeroDivisionError: division by zero
此外,增强的追溯功能所使用的信息可通过通用 API 获得,该 API 可用于关联 字节码 指令 与源代码位置。此信息可以使用以下方法检索
Python 中的
codeobject.co_positions()
方法。C API 中的
PyCode_Addr2Location()
函数。
有关更多详细信息,请参阅 PEP 657。(由 Pablo Galindo、Batuhan Taskaya 和 Ammar Askar 在 bpo-43950 中贡献。)
备注
此功能要求在 代码对象 中存储列位置,这可能会导致解释器内存使用量和编译后的 Python 文件磁盘使用量略有增加。为了避免存储额外信息并停用打印额外追溯信息,请使用 -X no_debug_ranges
命令行选项或 PYTHONNODEBUGRANGES
环境变量。
PEP 654: 异常组和 except*
¶
PEP 654 引入了语言功能,使程序能够同时引发和处理多个不相关的异常。内置类型 ExceptionGroup
和 BaseExceptionGroup
使得可以将异常分组并一起引发,新的 except*
语法将 except
泛化以匹配异常组的子组。
有关更多详细信息,请参阅 PEP 654。
(由 Irit Katriel 在 bpo-45292 中贡献。PEP 由 Irit Katriel、Yury Selivanov 和 Guido van Rossum 编写。)
PEP 678: 异常可添加注释¶
add_note()
方法已添加到 BaseException
。它可用于为异常添加在引发异常时不可用的上下文信息。添加的注释会出现在默认追溯中。
有关更多详细信息,请参阅 PEP 678。
(由 Irit Katriel 在 bpo-45607 中贡献。PEP 由 Zac Hatfield-Dodds 编写。)
Windows py.exe
启动器改进¶
Python 3.11 中包含的 Python 安装管理器 副本已显著更新。它现在支持 PEP 514 中定义的公司/标签语法,使用 -V:<company>/<tag>
参数,而不是有限的 -<major>.<minor>
。这允许启动 python.org 上托管的 PythonCore
之外的分发。
使用 -V:
选择器时,可以省略公司或标签,但会搜索所有安装。例如,-V:OtherPython/
将选择为 OtherPython
注册的“最佳”标签,而 -V:3.11
或 -V:/3.11
将选择标签为 3.11
的“最佳”分发。
使用旧的 -<major>
、-<major>.<minor>
、-<major>-<bitness>
或 -<major>.<minor>-<bitness>
参数时,所有现有行为都应保留与过去版本相同,并且只会选择 PythonCore
的发行版。然而,-64
后缀现在意味着“非 32 位”(不一定是 x86-64),因为有多个受支持的 64 位平台。32 位运行时通过检查运行时的标签是否包含 -32
后缀来检测。自 3.5 以来,所有 Python 版本都在其 32 位构建中包含了此后缀。
其他语言更改¶
现在允许在 异步函数 的推导式中使用异步 推导式。在这种情况下,外部推导式会隐式变为异步。(由 Serhiy Storchaka 在 bpo-33346 中贡献。)
对于不支持 上下文管理器 协议的对象,在
with
语句和contextlib.ExitStack.enter_context()
中现在会引发TypeError
而不是AttributeError
;对于不支持 异步上下文管理器 协议的对象,在async with
语句和contextlib.AsyncExitStack.enter_async_context()
中也一样。(由 Serhiy Storchaka 在 bpo-12022 和 bpo-44471 中贡献。)添加了
object.__getstate__()
,它提供了__getstate__()
方法的默认实现。复制copy
和pickle
内置类型bytearray
、set
、frozenset
、collections.OrderedDict
、collections.deque
、weakref.WeakSet
和datetime.tzinfo
的子类实例现在会复制和 pickle 作为 槽 实现的实例属性。此更改具有意外的副作用:它会绊倒少数现有 Python 项目,这些项目不期望object.__getstate__()
存在。有关此类代码可能需要的变通方法的讨论,请参阅 gh-70766 上的后续评论。(由 Serhiy Storchaka 在 bpo-26579 中贡献。)
添加了
-P
命令行选项和PYTHONSAFEPATH
环境变量,它们会禁用在运行脚本时将脚本目录自动添加到sys.path
,或者在使用-c
和-m
时将当前目录自动添加到sys.path
。这确保import
只会查找标准库和已安装的模块,并避免无意或恶意地使用本地(通常是用户可写)目录中的模块来遮盖模块。(由 Victor Stinner 在 gh-57684 中贡献。)格式化规范迷你语言 中添加了一个
"z"
选项,它在舍入到格式精度后将负零强制转换为正零。有关更多详细信息,请参阅 PEP 682。(由 John Belmonte 在 gh-90153 中贡献。)sys.path
不再接受字节。在 Python 3.2 和 3.6 之间某个时候,字节支持中断了,直到 Python 3.10.0 发布后才有人注意到。此外,由于-b
和sys.path_importer_cache
在str
和bytes
键混合时会发生交互,恢复支持会很麻烦。(由 Thomas Grainger 在 gh-91181 中贡献。)
其他 CPython 实现变更¶
为
complex
实现了特殊方法__complex__()
,为bytes
实现了__bytes__()
,以支持typing.SupportsComplex
和typing.SupportsBytes
协议。(由 Mark Dickinson 和 Donghee Na 在 bpo-24234 中贡献。)siphash13
被添加为新的内部哈希算法。它与siphash24
具有相似的安全属性,但对于长输入来说速度稍快。str
、bytes
和其他一些类型现在将其用作hash()
的默认算法。PEP 552 基于哈希的 .pyc 文件 现在也使用siphash13
。(由 Inada Naoki 在 bpo-29410 中贡献。)当活动异常由不带参数的
raise
语句重新引发时,附加到此异常的追溯现在始终是sys.exc_info()[1].__traceback__
。这意味着在当前except
子句中对追溯所做的更改会反映在重新引发的异常中。(由 Irit Katriel 在 bpo-45711 中贡献。)解释器状态中已处理异常的表示(即
exc_info
或_PyErr_StackItem
)现在只有exc_value
字段;exc_type
和exc_traceback
已被移除,因为它们可以从exc_value
派生。(由 Irit Katriel 在 bpo-45711 中贡献。)Windows 安装程序已添加新的 命令行选项
AppendPath
。它的行为与PrependPath
类似,但它会将安装和脚本目录附加到路径,而不是预置。(由 Bastian Neuburger 在 bpo-44934 中贡献。)现在必须将
PyConfig.module_search_paths_set
字段设置为1
,初始化才能使用PyConfig.module_search_paths
来初始化sys.path
。否则,初始化将重新计算路径并替换添加到module_search_paths
的任何值。--help
选项的输出现在适用于 50 行/80 列。有关 Python 环境变量 和-X
选项的信息现在可以通过相应的--help-env
和--help-xoptions
标志以及新的--help-all
获得。(由 Éric Araujo 在 bpo-46142 中贡献。)在除 2 (二进制)、4、8 (八进制)、16 (十六进制) 或 32 之外的基数(例如基数 10 (十进制))中,
int
和str
之间的转换,如果字符串形式的数字位数超过限制,现在会引发ValueError
>,以避免由于算法复杂性而导致的潜在拒绝服务攻击。这是对 CVE 2020-10735 的缓解措施。此限制可以通过环境变量、命令行标志或sys
API 进行配置或禁用。请参阅 整数字符串转换长度限制 文档。默认限制是字符串形式的 4300 位数字。
新模块¶
改进的模块¶
asyncio¶
添加了
TaskGroup
类,它是一个 异步上下文管理器,包含一组任务,退出时会等待所有任务。对于新代码,建议使用此方法,而不是直接使用create_task()
和gather()
。(由 Yury Selivanov 等人于 gh-90908 贡献。)添加了
timeout()
,一个用于设置异步操作超时的异步上下文管理器。对于新代码,建议使用此方法,而不是直接使用wait_for()
。(由 Andrew Svetlov 在 gh-90927 中贡献。)添加了
Runner
类,它暴露了run()
使用的机制。(由 Andrew Svetlov 在 gh-91218 中贡献。)在 asyncio 库的同步原语中添加了
Barrier
类,以及相关的BrokenBarrierError
异常。(由 Yves Duprat 和 Andrew Svetlov 在 gh-87518 中贡献。)向
asyncio.loop.create_connection()
添加了关键字参数 all_errors,以便可以将多个连接错误作为ExceptionGroup
抛出。添加了
asyncio.StreamWriter.start_tls()
方法,用于将现有基于流的连接升级到 TLS。(由 Ian Good 在 bpo-34975 中贡献。)向事件循环添加了原始数据报套接字函数:
sock_sendto()
、sock_recvfrom()
和sock_recvfrom_into()
。这些在SelectorEventLoop
和ProactorEventLoop
中都有实现。(由 Alex Grönholm 在 bpo-46805 中贡献。)向
Task
添加了cancelling()
和uncancel()
方法。这些主要用于内部使用,特别是由TaskGroup
使用。
contextlib¶
dataclasses¶
datetime¶
添加了
datetime.UTC
,作为datetime.timezone.utc
的便捷别名。(由 Kabir Kwatra 在 gh-91973 中贡献。)datetime.date.fromisoformat()
、datetime.time.fromisoformat()
和datetime.datetime.fromisoformat()
现在可以解析大多数 ISO 8601 格式(仅排除那些支持小数小时和分钟的格式)。(由 Paul Ganssle 在 gh-80010 中贡献。)
enum¶
将
EnumMeta
重命名为EnumType
(EnumMeta
仍保留为别名)。添加了
StrEnum
,其成员可以用作(且必须是)字符串。添加了
ReprEnum
,它只修改成员的__repr__()
,同时为__str__()
和__format__()
(由str()
、format()
和 f-string 使用)返回其字面值(而不是名称)。更改了
Enum.__format__()
(format()
、str.format()
和 f-string 的默认值)以始终产生与Enum.__str__()
相同的结果:对于继承自ReprEnum
的枚举,它将是成员的值;对于所有其他枚举,它将是枚举和成员名称(例如Color.RED
)。为
Flag
枚举和FlagBoundary
枚举添加了新的 boundary 类参数及其选项,以控制如何处理超出范围的标志值。添加了
member()
和nonmember()
装饰器,以确保被装饰的对象是/不是枚举成员。添加了
property()
装饰器,它像property()
一样工作,但用于枚举。使用它而不是types.DynamicClassAttribute()
。添加了
global_enum()
枚举装饰器,它调整__repr__()
和__str__()
,以将值显示为模块的成员,而不是枚举类。例如,re.RegexFlag
的ASCII
成员显示为're.ASCII'
,而不是'RegexFlag.ASCII'
。增强了
Flag
以支持对其成员使用len()
、迭代和in
/not in
。例如,现在以下代码可以工作:len(AFlag(3)) == 2 and list(AFlag(3)) == (AFlag.ONE, AFlag.TWO)
更改了
Enum
和Flag
,以便在调用__init_subclass__()
之前定义成员;dir()
现在包含来自混合数据类型的方法等。更改了
Flag
,使其只将主要值(2 的幂)视为规范值,而将复合值(3
、6
、10
等)视为别名;反转的标志会强制转换为其正等效值。
fcntl¶
在 FreeBSD 上,支持
F_DUP2FD
和F_DUP2FD_CLOEXEC
标志,前者等同于dup2
用法,后者则额外设置了FD_CLOEXEC
标志。
fractions¶
functools¶
functools.singledispatch()
现在支持将types.UnionType
和typing.Union
作为调度参数的注解。>>> from functools import singledispatch >>> @singledispatch ... def fun(arg, verbose=False): ... if verbose: ... print("Let me just say,", end=" ") ... print(arg) ... >>> @fun.register ... def _(arg: int | float, verbose=False): ... if verbose: ... print("Strength in numbers, eh?", end=" ") ... print(arg) ... >>> from typing import Union >>> @fun.register ... def _(arg: Union[list, set], verbose=False): ... if verbose: ... print("Enumerate this:") ... for i, elem in enumerate(arg): ... print(i, elem) ...
(由 Yurii Karabas 在 bpo-46014 中贡献。)
gzip¶
当
gzip.compress()
函数与 mtime=0 参数一起使用时,速度更快,因为它将压缩完全委托给单个zlib.compress()
操作。此更改有一个副作用:gzip 文件头包含一个“OS”字节。传统上,gzip
模块总是将其设置为代表“未知”的值 255。现在,当使用 mtime=0 调用compress()
时,它可能会被 Python 链接到的底层 zlib C 库设置为不同的值。(有关副作用的详细信息,请参阅 gh-112346。)
hashlib¶
hashlib.blake2b()
和hashlib.blake2s()
现在更喜欢 libb2,而不是 Python 内置的副本。(由 Christian Heimes 在 bpo-47095 中贡献。)SHA3 和 SHAKE 算法的内部
_sha3
模块现在使用 *tiny_sha3* 而不是 *Keccak Code Package*,以减少代码和二进制大小。hashlib
模块更喜欢 OpenSSL 中优化的 SHA3 和 SHAKE 实现。此更改仅影响没有 OpenSSL 支持的安装。(由 Christian Heimes 在 bpo-47098 中贡献。)添加了
hashlib.file_digest()
,一个用于高效哈希文件或类文件对象的辅助函数。(由 Christian Heimes 在 gh-89313 中贡献。)
IDLE 和 idlelib¶
inspect¶
添加
getmembers_static()
以返回所有成员,而不会通过描述符协议触发动态查找。(由 Weipeng Hong 在 bpo-30533 中贡献。)添加
ismethodwrapper()
用于检查对象的类型是否为MethodWrapperType
。(由 Hakan Çelik 在 bpo-29418 中贡献。)更改了
inspect
模块中与帧相关的函数,以返回新的FrameInfo
和Traceback
类实例(与以前的 命名元组 类似接口向后兼容),其中包括扩展的 PEP 657 位置信息(结束行号、列和结束列)。受影响的函数包括(由 Pablo Galindo 在 gh-88116 中贡献。)
locale¶
添加
locale.getencoding()
以获取当前 locale 编码。它类似于locale.getpreferredencoding(False)
,但忽略 Python UTF-8 模式。
logging¶
添加了
getLevelNamesMapping()
以返回日志级别名称(例如'CRITICAL'
)到其相应 日志级别 值(例如默认情况下为50
)的映射。(由 Andrei Kulakovin 在 gh-88024 中贡献。)为
SysLogHandler
添加了createSocket()
方法,以匹配SocketHandler.createSocket()
。它在处理程序初始化期间和在没有活动套接字时发出事件时自动调用。(由 Kirill Pinchuk 在 gh-88457 中贡献。)
math¶
添加
math.exp2()
:返回 2 的 x 次幂。(由 Gideon Mitchell 在 bpo-45917 中贡献。)添加
math.cbrt()
:返回 x 的立方根。(由 Ajith Ramachandran 在 bpo-44357 中贡献。)为了与 IEEE 754 规范保持一致,更改了两个
math.pow()
角点情况的行为。操作math.pow(0.0, -math.inf)
和math.pow(-0.0, -math.inf)
现在返回inf
。以前它们会引发ValueError
。(由 Mark Dickinson 在 bpo-44339 中贡献。)
operator¶
添加了一个新函数
operator.call
,使得operator.call(obj, *args, **kwargs) == obj(*args, **kwargs)
。(由 Antony Lee 在 bpo-44019 中贡献。)
os¶
在 Windows 上,
os.urandom()
现在使用BCryptGenRandom()
,而不是已废弃的CryptGenRandom()
。(由 Donghee Na 在 bpo-44611 中贡献。)
pathlib¶
re¶
原子分组 (
(?>...)
) 和占有式量词 (*+
,++
,?+
,{m,n}+
) 现在在正则表达式中受支持。(由 Jeffrey C. Jacobs 和 Serhiy Storchaka 在 bpo-433030 中贡献。)
shutil¶
在
shutil.rmtree()
中添加可选参数 dir_fd。(由 Serhiy Storchaka 在 bpo-46245 中贡献。)
socket¶
添加对 NetBSD 的 CAN Socket 支持。(由 Thomas Klausner 在 bpo-30512 中贡献。)
create_connection()
有一个选项,在连接失败时,抛出包含所有错误的ExceptionGroup
>,而不是只抛出最后一个错误。(由 Irit Katriel 在 bpo-29980 中贡献。)
sqlite3¶
现在可以通过将
None
传递给set_authorizer()
来禁用授权器。(由 Erlend E. Aasland 在 bpo-44491 中贡献。)create_collation()
的排序规则名称现在可以包含任何 Unicode 字符。包含无效字符的排序规则名称现在会引发UnicodeEncodeError
而不是sqlite3.ProgrammingError
。(由 Erlend E. Aasland 在 bpo-44688 中贡献。)sqlite3
异常现在包含 SQLite 扩展错误代码作为sqlite_errorcode
,以及 SQLite 错误名称作为sqlite_errorname
。(由 Aviv Palivoda、Daniel Shahaf 和 Erlend E. Aasland 在 bpo-16379 和 bpo-24139 中贡献。)在
sqlite3.Connection
中添加了setlimit()
和getlimit()
,用于按连接设置和获取 SQLite 限制。(由 Erlend E. Aasland 在 bpo-45243 中贡献。)sqlite3
现在根据底层 SQLite 库编译时使用的默认线程模式设置sqlite3.threadsafety
。(由 Erlend E. Aasland 在 bpo-45613 中贡献。)sqlite3
C 回调现在在启用回调追溯时使用不可引发的异常。用户现在可以注册不可引发的 钩子 处理程序
以改善他们的调试体验。(由 Erlend E. Aasland 在 bpo-45828 中贡献。)回滚后获取不再引发
InterfaceError
。相反,我们让 SQLite 库处理这些情况。(由 Erlend E. Aasland 在 bpo-44092 中贡献。)在
sqlite3.Connection
中添加了serialize()
和deserialize()
,用于序列化和反序列化数据库。(由 Erlend E. Aasland 在 bpo-41930 中贡献。)在
sqlite3.Connection
中添加create_window_function()
,用于创建聚合窗口函数。(由 Erlend E. Aasland 在 bpo-34916 中贡献)。在
sqlite3.Connection
中添加blobopen()
。sqlite3.Blob
允许对 BLOB 进行增量 I/O 操作。(由 Aviv Palivoda 和 Erlend E. Aasland 在 bpo-24905 中贡献)。
string¶
向
string.Template
添加get_identifiers()
和is_valid()
,它们分别返回所有有效的占位符,以及是否存在任何无效的占位符。(由 Ben Kehoe 在 gh-90465 中贡献)。
sys¶
sys.exc_info()
现在从value
(异常实例) 派生type
和traceback
字段,因此当异常在处理过程中被修改时,这些更改会反映在后续调用exc_info()
的结果中。(由 Irit Katriel 在 bpo-45711 中贡献)。添加
sys.exception()
,它返回活动的异常实例 (等同于sys.exc_info()[1]
)。(由 Irit Katriel 在 bpo-46328 中贡献)。添加
sys.flags.safe_path
标志。(由 Victor Stinner 在 gh-57684 中贡献)。
sysconfig¶
新增了三个 安装方案(*posix_venv*、*nt_venv* 和 *venv*),它们在 Python 创建新的虚拟环境或从虚拟环境运行时使用。前两个方案(*posix_venv* 和 *nt_venv*)是针对非 Windows 和 Windows 的操作系统特定方案,而 *venv* 实际上是根据 Python 运行的操作系统而对其中一个方案的别名。这对于修改
sysconfig.get_preferred_scheme()
的下游分发商非常有用。创建新虚拟环境的第三方代码应使用新的 *venv* 安装方案来确定路径,就像venv
所做的那样。(由 Miro Hrončok 在 bpo-45413 中贡献)。
tempfile¶
SpooledTemporaryFile
对象现在完全实现了io.BufferedIOBase
或io.TextIOBase
的方法(取决于文件模式)。这使得它们可以与期望文件类对象的 API (例如压缩模块) 正确工作。(由 Carey Metcalfe 在 gh-70363 中贡献)。
threading¶
在 Unix 上,如果 C 库中提供了
sem_clockwait()
函数(glibc 2.30 及更高版本),则threading.Lock.acquire()
方法现在使用单调时钟 (time.CLOCK_MONOTONIC
) 作为超时,而不是使用系统时钟 (time.CLOCK_REALTIME
),以避免受系统时钟变化的影响。(由 Victor Stinner 在 bpo-41710 中贡献)。
时间¶
在 Unix 上,
time.sleep()
现在使用clock_nanosleep()
或nanosleep()
函数(如果可用),其分辨率为 1 纳秒(10-9 秒),而不是使用分辨率为 1 微秒(10-6 秒)的select()
。(由 Benjamin Szőke 和 Victor Stinner 在 bpo-21302 中贡献)。在 Windows 8.1 及更高版本中,
time.sleep()
现在使用基于 高分辨率计时器 的可等待计时器,其分辨率为 100 纳秒(10-7 秒)。之前,它的分辨率为 1 毫秒(10-3 秒)。(由 Benjamin Szőke、Donghee Na、Eryk Sun 和 Victor Stinner 在 bpo-21302 和 bpo-45429 中贡献)。
tkinter¶
添加了方法
info_patchlevel()
,它以与sys.version_info
类似的具名元组形式返回 Tcl 库的精确版本。(由 Serhiy Storchaka 在 gh-91827 中贡献)。
traceback¶
添加
traceback.StackSummary.format_frame_summary()
,允许用户覆盖哪些帧出现在回溯中,以及如何格式化它们。(由 Ammar Askar 在 bpo-44569 中贡献)。添加
traceback.TracebackException.print()
,它将格式化的TracebackException
实例打印到文件。(由 Irit Katriel 在 bpo-33809 中贡献)。
typing¶
有关主要更改,请参见 与类型提示相关的新特性。
添加
typing.assert_never()
和typing.Never
。typing.assert_never()
对于要求类型检查器确认一行代码不可达很有用。在运行时,它会引发AssertionError
。(由 Jelle Zijlstra 在 gh-90633 中贡献)。添加
typing.reveal_type()
。这对于要求类型检查器推断给定表达式的类型很有用。在运行时,它会打印接收值的类型。(由 Jelle Zijlstra 在 gh-90572 中贡献)。添加
typing.assert_type()
。这对于要求类型检查器确认其推断的给定表达式的类型与给定类型匹配很有用。在运行时,它只是返回接收到的值。(由 Jelle Zijlstra 在 gh-90638 中贡献)。typing.TypedDict
类型现在可以是泛型的。(由 Samodya Abeysiriwardane 在 gh-89026 中贡献)。NamedTuple
类型现在可以是泛型的。(由 Serhiy Storchaka 在 bpo-43923 中贡献)。允许
typing.Any
的子类化。这对于避免与高度动态类(例如模拟对象)相关的类型检查器错误很有用。(由 Shantanu Jain 在 gh-91154 中贡献)。typing.final()
装饰器现在在被装饰的对象上设置__final__
属性。(由 Jelle Zijlstra 在 gh-90500 中贡献)。typing.get_overloads()
函数可用于内省函数的重载。typing.clear_overloads()
可用于清除函数的所有已注册重载。(由 Jelle Zijlstra 在 gh-89263 中贡献)。Protocol
子类的__init__()
方法现在得以保留。(由 Adrian Garcia Badarasco 在 gh-88970 中贡献)。空元组类型 (
Tuple[()]
) 的表示被简化。这会影响内省,例如get_args(Tuple[()])
现在求值为()
而不是((),)
。(由 Serhiy Storchaka 在 gh-91137 中贡献)。通过移除私有
typing._type_check
函数中的可调用检查,放宽了类型注释的运行时要求。(由 Gregory Beauregard 在 gh-90802 中贡献)。typing.get_type_hints()
现在支持在 PEP 585 泛型别名 中将字符串评估为前向引用。(由 Niklas Rosenstein 在 gh-85542 中贡献)。typing.get_type_hints()
不再向默认值为None
的参数添加Optional
。(由 Nikita Sobolev 在 gh-90353 中贡献)。typing.get_type_hints()
现在支持评估裸字符串化ClassVar
注释。(由 Gregory Beauregard 在 gh-90711 中贡献)。typing.no_type_check()
不再修改外部类和函数。它现在也正确地将类方法标记为不进行类型检查。(由 Nikita Sobolev 在 gh-90729 中贡献)。
unicodedata¶
Unicode 数据库已更新至版本 14.0.0。(由 Benjamin Peterson 在 bpo-45190 中贡献)。
unittest¶
添加了
TestCase
类的enterContext()
和enterClassContext()
方法,IsolatedAsyncioTestCase
类的enterAsyncContext()
方法以及unittest.enterModuleContext()
函数。(由 Serhiy Storchaka 在 bpo-45046 中贡献)。
venv¶
创建新的 Python 虚拟环境时,会使用 *venv* sysconfig 安装方案 来确定环境内的路径。当 Python 在虚拟环境中运行时,相同的安装方案是默认的。这意味着下游分发商可以在不改变虚拟环境行为的情况下更改默认的 sysconfig 安装方案。创建新虚拟环境的第三方代码也应该这样做。(由 Miro Hrončok 在 bpo-45413 中贡献)。
warnings¶
warnings.catch_warnings()
现在接受warnings.simplefilter()
的参数,提供了一种更简洁的方式来局部忽略警告或将其转换为错误。(由 Zac Hatfield-Dodds 在 bpo-47074 中贡献)。
zipfile¶
新增了在
ZipFile
目录和文件头中指定成员名编码以读取元数据的支持。(由 Stephen J. Turnbull 和 Serhiy Storchaka 在 bpo-28080 中贡献)。新增了
ZipFile.mkdir()
,用于在 ZIP 归档中创建新目录。(由 Sam Ezeh 在 gh-49083 中贡献)。为
zipfile.Path
添加了stem
、suffix
和suffixes
。(由 Miguel Brito 在 gh-88261 中贡献)。
优化¶
本节介绍与 更快的 CPython 项目无关的特定优化,该项目在单独的章节中介绍。
编译器现在优化了字符串字面量中只包含格式代码
%s
、%r
和%a
的简单 printf 风格的 % 格式化,使其与相应的 f 字符串 表达式一样快。(由 Serhiy Storchaka 在 bpo-28307 中贡献)。整数除法 (
//
) 更好地针对编译器优化进行了调整。在 x86-64 上,当用小于2**30
的值除以int
时,它的速度现在提高了大约 20%。(由 Gregory P. Smith 和 Tim Peters 在 gh-90564 中贡献)。对于小于
2**30
的整数,sum()
现在快了近 30%。(由 Stefan Behnel 在 gh-68264 中贡献)。列表大小调整在常见情况下得到了优化,将
list.append()
的速度提高了约 15%,简单的 列表推导式 提高了 20-30%。(由 Dennis Sweeney 在 gh-91165 中贡献)。当所有键都是 Unicode 对象时,字典不再存储哈希值,从而减小了
dict
的大小。例如,在 64 位平台上,sys.getsizeof(dict.fromkeys("abcdefg"))
从 352 字节减少到 272 字节(小 23%)。(由 Inada Naoki 在 bpo-46845 中贡献)。在使用
asyncio.DatagramProtocol
通过 UDP 传输大文件时,现在速度快了几个数量级,对于约 60 MiB 的文件,速度提高了 100 多倍。(由 msoxzw 在 gh-91487 中贡献)。math
函数comb()
和perm()
对于大参数现在快了约 10 倍(对于更大的 *k*,加速更大)。(由 Serhiy Storchaka 在 bpo-37295 中贡献)。statistics
函数mean()
、variance()
和stdev()
现在以一次性遍历的方式消耗迭代器,而不是先将其转换为list
。这使速度提高了一倍,并可以节省大量内存。(由 Raymond Hettinger 在 gh-90415 中贡献)。unicodedata.normalize()
现在以常数时间规范化纯 ASCII 字符串。(由 Donghee Na 在 bpo-44987 中贡献)。
更快的 CPython¶
在 Ubuntu Linux 上使用 GCC 编译时,CPython 3.11 在 pyperformance 基准测试套件中,平均比 CPython 3.10 快 25%。根据您的工作负载,整体加速可能在 10-60% 之间。
该项目专注于 Python 的两个主要领域:更快的启动 和 更快的运行时。不在此项目范围内的优化将在 优化 部分单独列出。
更快的启动¶
冻结导入 / 静态代码对象¶
Python 将 字节码 缓存在 __pycache__ 目录中,以加快模块加载。
以前在 3.10 中,Python 模块执行过程如下
Read __pycache__ -> Unmarshal -> Heap allocated code object -> Evaluate
在 Python 3.11 中,Python 启动所需的核心模块是“冻结”的。这意味着它们的 代码对象(和字节码)由解释器静态分配。这减少了模块执行过程中的步骤,变为
Statically allocated code object -> Evaluate
Python 3.11 的解释器启动速度现在快了 10-15%。这对于使用 Python 的短时运行程序影响很大。
(由 Eric Snow、Guido van Rossum 和 Kumar Aditya 在许多问题中贡献)。
更快的运行时¶
更廉价、惰性的 Python 帧¶
每当 Python 调用 Python 函数时,都会创建保存执行信息的 Python 帧。以下是新的帧优化:
简化了帧创建过程。
通过在 C 栈上大量重用帧空间来避免内存分配。
简化了内部帧结构,使其只包含基本信息。帧以前包含额外的调试和内存管理信息。
旧式的 帧对象 现在只在调试器请求或 Python 内省函数(如 sys._getframe()
和 inspect.currentframe()
)请求时创建。对于大多数用户代码,根本不创建帧对象。因此,几乎所有 Python 函数调用都显著加速。我们在 pyperformance 中测量到 3-7% 的加速。(由 Mark Shannon 在 bpo-44590 中贡献)。
(由 Mark Shannon 在 bpo-44590 中贡献)。
内联 Python 函数调用¶
在 Python 函数调用期间,Python 将调用一个求值 C 函数来解释该函数的代码。这有效地将纯 Python 递归限制在 C 栈的安全范围内。
在 3.11 中,当 CPython 检测到 Python 代码调用另一个 Python 函数时,它会设置一个新帧,并“跳到”新帧中的新代码。这完全避免了调用 C 解释函数。
大多数 Python 函数调用现在不消耗 C 栈空间,从而加快了它们的速度。在简单的递归函数(如斐波那契或阶乘)中,我们观察到 1.7 倍的加速。这也意味着递归函数可以递归更深(如果用户使用 sys.setrecursionlimit()
增加了递归限制)。我们在 pyperformance 中测量到 1-3% 的改进。
(由 Pablo Galindo 和 Mark Shannon 在 bpo-45256 中贡献)。
PEP 659: 特化自适应解释器¶
PEP 659 是 Faster CPython 项目的关键部分之一。其基本思想是,尽管 Python 是一种动态语言,但大多数代码都有对象和类型很少变化的区域。这个概念被称为 *类型稳定性*。
在运行时,Python 将尝试在执行代码中寻找常见模式和类型稳定性。然后,Python 将当前操作替换为更专业的特殊操作。这种特殊操作使用只有这些用例/类型才可用的快速路径,通常比其通用对应项表现更好。这还引入了另一个概念,称为 *内联缓存*,其中 Python 将昂贵操作的结果直接缓存在 字节码 中。
特化器还将某些常见的指令对组合成一个超指令,从而减少执行期间的开销。
Python 只会在看到“热”代码(执行多次)时进行特化。这可以防止 Python 浪费时间在一次性代码上。当代码过于动态或用途发生变化时,Python 也可以取消特化。特化会定期尝试,并且特化尝试的成本不高,这使得特化能够适应新情况。
(PEP 由 Mark Shannon 编写,灵感来自 Stefan Brunthaler 的想法。有关更多信息,请参见 PEP 659。由 Mark Shannon 和 Brandt Bucher 实现,Irit Katriel 和 Dennis Sweeney 提供了额外帮助)。
操作 |
形式 |
专业化 |
操作加速 (最高) |
贡献者 |
---|---|---|---|---|
二元运算 |
|
10% |
Mark Shannon, Donghee Na, Brandt Bucher, Dennis Sweeney |
|
下标 |
|
下标容器类型,例如 自定义 |
10-25% |
Irit Katriel, Mark Shannon |
存储下标 |
|
类似于上面的下标特化。 |
10-25% |
Dennis Sweeney |
调用 |
|
20% |
Mark Shannon, Ken Jin |
|
加载全局变量 |
|
对象在全局/内置命名空间中的索引被缓存。加载全局和内置变量无需命名空间查找。 |
Mark Shannon |
|
加载属性 |
|
类似于加载全局变量。属性在类/对象的命名空间中的索引被缓存。在大多数情况下,属性加载不需要命名空间查找。 |
Mark Shannon |
|
调用方法 |
|
方法的实际地址被缓存。现在方法加载没有命名空间查找——即使对于具有长继承链的类也是如此。 |
10-20% |
Ken Jin, Mark Shannon |
存储属性 |
|
类似于加载属性优化。 |
在 pyperformance 中提高 2% |
Mark Shannon |
解包序列 |
|
8% |
Brandt Bucher |
其他¶
由于惰性创建的对象命名空间,对象现在需要更少的内存。它们的命名空间字典现在也更自由地共享键。(由 Mark Shannon 在 bpo-45340 和 bpo-40116 中贡献)。
实现了“零成本”异常,消除了在未引发异常时
try
语句的开销。(由 Mark Shannon 在 bpo-40222 中贡献)。解释器中更简洁的异常表示将捕获异常所需的时间减少了约 10%。(由 Irit Katriel 在 bpo-45711 中贡献)。
re
的正则表达式匹配引擎已部分重构,现在在支持的平台上使用计算 goto(或“线程代码”)。因此,Python 3.11 执行 pyperformance 正则表达式基准测试 的速度比 Python 3.10 快 10%。(由 Brandt Bucher 在 gh-91404 中贡献)。
常见问题¶
我应该如何编写代码来利用这些加速?¶
编写遵循常见最佳实践的 Pythonic 代码;您无需更改代码。Faster CPython 项目优化了我们观察到的常见代码模式。
CPython 3.11 会使用更多内存吗?¶
可能不会;我们预计内存使用量不会超过 3.10 的 20%。这可以通过上面提到的帧对象和对象字典的内存优化来抵消。
我的工作负载中没有看到任何加速。为什么?¶
某些代码不会有明显的收益。如果您的代码大部分时间花在 I/O 操作上,或者大部分计算已经在 NumPy 等 C 扩展库中完成,则不会有显著的加速。该项目目前对纯 Python 工作负载的收益最大。
此外,pyperformance 的数据是几何平均值。即使在 pyperformance 基准测试中,某些基准测试略有减慢,而另一些则加速了近 2 倍!
有 JIT 编译器吗?¶
没有。我们仍在探索其他优化。
关于¶
Faster CPython 探索了 CPython 的优化。主要团队由微软资助,全职从事这项工作。Pablo Galindo Salgado 也由 Bloomberg LP 资助,兼职从事该项目。最后,许多贡献者是社区的志愿者。
CPython 字节码变更¶
字节码现在包含内联缓存条目,它们以新添加的 CACHE
指令的形式存在。许多操作码期望后面跟着确切数量的缓存,并指示解释器在运行时跳过它们。填充的缓存可以看起来像任意指令,因此在读取或修改包含加速数据的原始、自适应字节码时应格外小心。
新操作码¶
ASYNC_GEN_WRAP
、RETURN_GENERATOR
和SEND
,用于生成器和协程。COPY_FREE_VARS
,避免了闭包所需的特殊调用者侧代码。JUMP_BACKWARD_NO_INTERRUPT
,用于某些不希望处理中断的循环。CHECK_EG_MATCH
和PREP_RERAISE_STAR
,用于处理 PEP 654 中添加的 新的异常组和 except*。PUSH_EXC_INFO
,用于异常处理程序。RESUME
,一个无操作,用于内部跟踪、调试和优化检查。
替换的操作码¶
替换的操作码 |
新操作码 |
备注 |
---|---|---|
BINARY_* INPLACE_* |
将所有数值二元/原地操作码替换为单个操作码 |
|
CALL_FUNCTION CALL_FUNCTION_KW CALL_METHOD |
将方法的参数移位与关键字参数处理解耦;允许更好的调用特化 |
|
DUP_TOP DUP_TOP_TWO ROT_TWO ROT_THREE ROT_FOUR ROT_N |
栈操作指令 |
|
JUMP_IF_NOT_EXC_MATCH |
现在执行检查但不跳转 |
|
JUMP_ABSOLUTE POP_JUMP_IF_FALSE POP_JUMP_IF_TRUE |
参见 [3];每个方向的 |
|
SETUP_WITH SETUP_ASYNC_WITH |
|
|
所有跳转操作码现在都是相对的,包括现有的 JUMP_IF_TRUE_OR_POP
和 JUMP_IF_FALSE_OR_POP
。参数现在是相对于当前指令的偏移量,而不是绝对位置。
更改/移除的操作码¶
更改了
MATCH_CLASS
和MATCH_KEYS
,使其不再推送一个额外的布尔值来指示成功/失败。相反,在失败时,会推送None
来代替提取值的元组。更改了处理异常的操作码,以反映它们现在在栈上表示为一个项,而不是三个项(请参阅 gh-89874)。
移除了
COPY_DICT_WITHOUT_KEYS
、GEN_START
、POP_BLOCK
、SETUP_FINALLY
和YIELD_FROM
。
已弃用¶
本节列出了 Python 3.11 中已弃用的 Python API。
已弃用的 C API 单独列出。
语言/内置¶
链接
classmethod
描述符(在 bpo-19072 中引入)现在已弃用。它不能再用于包装其他描述符,例如property
。此功能的核心设计存在缺陷,并导致了一些下游问题。要“传递”一个classmethod
,请考虑使用 Python 3.10 中添加的__wrapped__
属性。(由 Raymond Hettinger 在 gh-89519 中贡献)。字符串和字节字面量中八进制转义符的值大于
0o377
(十进制 255)现在会产生DeprecationWarning
。在未来的 Python 版本中,它们将引发SyntaxWarning
,并最终引发SyntaxError
。(由 Serhiy Storchaka 在 gh-81548 中贡献)。int()
对__trunc__()
的委托现在已弃用。当type(a)
实现了__trunc__()
但没有实现__int__()
或__index__()
时,调用int(a)
现在会引发DeprecationWarning
。(由 Zackery Spytz 在 bpo-44977 中贡献)。
模块¶
PEP 594 导致以下模块被弃用,并计划在 Python 3.13 中移除:
aifc
chunk
msilib
pipes
telnetlib
audioop
crypt
nis
sndhdr
uu
cgi
imghdr
nntplib
spwd
xdrlib
cgitb
mailcap
ossaudiodev
sunau
(由 Brett Cannon 在 bpo-47061 和 Victor Stinner 在 gh-68966 中贡献)。
asynchat
、asyncore
和smtpd
模块自 Python 3.6 以来已被弃用。它们的文档和弃用警告已更新,以指出它们将在 Python 3.12 中移除。(由 Hugo van Kemenade 在 bpo-47022 中贡献)。lib2to3
包和2to3
工具现已弃用,可能无法解析 Python 3.10 或更高版本。有关详细信息,请参见引入新 PEG 解析器的 PEP 617。(由 Victor Stinner 在 bpo-40360 中贡献)。未文档化的模块
sre_compile
、sre_constants
和sre_parse
现已弃用。(由 Serhiy Storchaka 在 bpo-47152 中贡献)。
标准库¶
以下内容已在
configparser
中自 Python 3.2 以来被弃用。它们的弃用警告现已更新,以指出它们将在 Python 3.12 中移除:configparser.SafeConfigParser
类configparser.ParsingError.filename
属性configparser.RawConfigParser.readfp()
方法
(由 Hugo van Kemenade 在 bpo-45173 中贡献)。
configparser.LegacyInterpolation
自 Python 3.2 以来在文档字符串中已弃用,并且未在configparser
文档中列出。它现在会发出DeprecationWarning
,并将在 Python 3.13 中移除。请改用configparser.BasicInterpolation
或configparser.ExtendedInterpolation
。(由 Hugo van Kemenade 在 bpo-46607 中贡献)。较旧的
importlib.resources
函数集已弃用,取而代之的是 Python 3.9 中添加的新函数,并且将在未来的 Python 版本中移除,因为它们不支持包子目录中的资源:importlib.resources.contents()
importlib.resources.is_resource()
importlib.resources.open_binary()
importlib.resources.open_text()
importlib.resources.read_binary()
importlib.resources.read_text()
importlib.resources.path()
locale.getdefaultlocale()
函数已弃用,并将在 Python 3.15 中移除。请改用locale.setlocale()
、locale.getpreferredencoding(False)
和locale.getlocale()
函数。(由 Victor Stinner 在 gh-90817 中贡献)。locale.resetlocale()
函数已弃用,并将在 Python 3.13 中移除。请改用locale.setlocale(locale.LC_ALL, "")
。(由 Victor Stinner 在 gh-90817 中贡献)。现在,针对 正则表达式 中的数字组引用和组名将应用更严格的规则。现在,只有 ASCII 数字序列才会被接受为数字引用,并且
bytes
模式和替换字符串中的组名只能包含 ASCII 字母、数字和下划线。目前,违反这些规则的语法会引发弃用警告。(由 Serhiy Storchaka 在 gh-91760 中贡献)。在
re
模块中,re.template()
函数以及相应的re.TEMPLATE
和re.T
标志已弃用,因为它们未文档化且缺乏明确的目的。它们将在 Python 3.13 中移除。(由 Serhiy Storchaka 和 Miro Hrončok 在 gh-92728 中贡献)。turtle.settiltangle()
自 Python 3.1 以来已被弃用;它现在会发出弃用警告,并将在 Python 3.13 中移除。请改用turtle.tiltangle()
(它之前被错误地标记为已弃用,现在其文档字符串已更正)。(由 Hugo van Kemenade 在 bpo-45837 中贡献)。typing.Text
仅用于提供 Python 2 和 Python 3 代码之间的兼容性支持,现已弃用。目前尚未计划将其移除,但鼓励用户在可能的情况下使用str
。(由 Alex Waygood 在 gh-92332 中贡献)。用于构建
typing.TypedDict
类型的关键字参数语法现已弃用。Python 3.13 中将移除支持。(由 Jingchen Ye 在 gh-90224 中贡献)。webbrowser.MacOSX
已弃用,并将在 Python 3.13 中移除。它未经测试,未文档化,并且webbrowser
本身不使用它。(由 Donghee Na 在 bpo-42255 中贡献)。从
TestCase
和IsolatedAsyncioTestCase
测试方法返回非默认None
值的行为现在已被弃用。弃用了以下未正式文档化的
unittest
函数,计划在 Python 3.13 中移除:unittest.findTestCases()
unittest.makeSuite()
unittest.getTestCaseNames()
请改用
TestLoader
方法:(由 Erlend E. Aasland 在 bpo-5846 中贡献)。
unittest.TestProgram.usageExit()
被标记为已弃用,将在 3.13 中移除。(由 Carlos Damázio 在 gh-67048 中贡献)。
计划在 Python 3.12 中移除¶
以下 Python API 已在之前的 Python 版本中弃用,并将在 Python 3.12 中移除。
计划移除的 C API 单独列出。
asynchat
模块asyncore
模块imp
模块typing.io
命名空间typing.re
命名空间cgi.log()
importlib.find_loader()
importlib.abc.Loader.module_repr()
importlib.abc.MetaPathFinder.find_module()
importlib.abc.PathEntryFinder.find_loader()
importlib.abc.PathEntryFinder.find_module()
importlib.machinery.BuiltinImporter.find_module()
importlib.machinery.BuiltinLoader.module_repr()
importlib.machinery.FileFinder.find_loader()
importlib.machinery.FileFinder.find_module()
importlib.machinery.FrozenImporter.find_module()
importlib.machinery.FrozenLoader.module_repr()
importlib.machinery.PathFinder.find_module()
importlib.machinery.WindowsRegistryFinder.find_module()
importlib.util.module_for_loader()
importlib.util.set_loader_wrapper()
importlib.util.set_package_wrapper()
pkgutil.ImpImporter
pkgutil.ImpLoader
pathlib.Path.link_to()
sqlite3.enable_shared_cache()
sqlite3.OptimizedUnicode()
PYTHONTHREADDEBUG
环境变量以下
unittest
中已弃用的别名:已弃用的别名
方法名
弃用版本
failUnless
3.1
failIf
3.1
failUnlessEqual
3.1
failIfEqual
3.1
failUnlessAlmostEqual
3.1
failIfAlmostEqual
3.1
failUnlessRaises
3.1
assert_
3.2
assertEquals
3.2
assertNotEquals
3.2
assertAlmostEquals
3.2
assertNotAlmostEquals
3.2
assertRegexpMatches
3.2
assertRaisesRegexp
3.2
assertNotRegexpMatches
3.5
已移除¶
本节列出了 Python 3.11 中已移除的 Python API。
已移除的 C API 单独列出。
移除了
@asyncio.coroutine()
装饰器,该装饰器曾使基于旧版生成器的协程能够与async
/await
代码兼容。此函数自 Python 3.8 起已被弃用,并原定于 Python 3.10 中移除。请改用async def
。(由 Illia Volochii 在 bpo-43216 中贡献。)移除了
asyncio.coroutines.CoroWrapper
,该类用于在调试模式下包装基于旧版生成器的协程对象。(由 Illia Volochii 在 bpo-43216 中贡献。)由于重大的安全问题,
asyncio.loop.create_datagram_endpoint()
的 reuse_address 参数(在 Python 3.9 中禁用)现在已完全移除。这是由于SO_REUSEADDR
套接字选项在 UDP 中的行为所致。(由 Hugo van Kemenade 在 bpo-45129 中贡献。)移除了
binhex
模块,该模块在 Python 3.9 中已被弃用。同时移除了相关且同样已被弃用的binascii
函数:binascii.a2b_hqx()
binascii.b2a_hqx()
binascii.rlecode_hqx()
binascii.rldecode_hqx()
binascii.crc_hqx()
函数仍然可用。(由 Victor Stinner 在 bpo-45085 中贡献。)
移除了
distutils
的bdist_msi
命令,该命令在 Python 3.9 中已被弃用。请改用bdist_wheel
(wheel 包)。(由 Hugo van Kemenade 在 bpo-45124 中贡献。)移除了
xml.dom.pulldom.DOMEventStream
、wsgiref.util.FileWrapper
和fileinput.FileInput
的__getitem__()
方法,这些方法自 Python 3.9 起已被弃用。(由 Hugo van Kemenade 在 bpo-45132 中贡献。)移除了已弃用的
gettext
函数lgettext()
、ldgettext()
、lngettext()
和ldngettext()
。同时移除了bind_textdomain_codeset()
函数、NullTranslations.output_charset()
和NullTranslations.set_output_charset()
方法,以及translation()
和install()
的 codeset 参数,因为它们仅用于l*gettext()
函数。(由 Donghee Na 和 Serhiy Storchaka 在 bpo-44235 中贡献。)从
inspect
模块中移除:getargspec()
函数,该函数自 Python 3.0 起已被弃用;请改用inspect.signature()
或inspect.getfullargspec()
。formatargspec()
函数,该函数自 Python 3.5 起已被弃用;请改用inspect.signature()
函数或直接使用inspect.Signature
对象。未文档化的
Signature.from_builtin()
和Signature.from_function()
方法,这些方法自 Python 3.5 起已被弃用;请改用Signature.from_callable()
方法。
(由 Hugo van Kemenade 在 bpo-45320 中贡献。)
从
pathlib.PurePath
中移除了__class_getitem__()
方法,因为它未被使用且在早期版本中因错误而添加。(由 Nikita Sobolev 在 bpo-46483 中贡献。)移除了
smtpd
模块中的MailmanProxy
类,因为它在没有外部mailman
包的情况下无法使用。(由 Donghee Na 在 bpo-35800 中贡献。)移除了
_tkinter.TkappType
中已弃用的split()
方法。(由 Erlend E. Aasland 在 bpo-38371 中贡献。)移除了
unittest
发现功能中的命名空间包支持。该功能在 Python 3.4 中引入,但自 Python 3.7 起已损坏。(由 Inada Naoki 在 bpo-23882 中贡献。)移除了未文档化的私有
float.__set_format__()
方法,该方法在 Python 3.7 中曾被称为float.__setformat__()
。其文档字符串写道:“您可能不想使用此函数。它主要用于 Python 的测试套件。”(由 Victor Stinner 在 bpo-46852 中贡献。)--experimental-isolated-subinterpreters
配置标志(以及相应的EXPERIMENTAL_ISOLATED_SUBINTERPRETERS
宏)已被移除。Pynche —— Pythonic自然色彩和色调编辑器 —— 已从
Tools/scripts
移出,并 独立于 Python 源代码树进行开发。
移植到 Python 3.11¶
本节列出了之前描述的更改以及 Python API 中可能需要更改您的 Python 代码的其他错误修复。
C API 的移植说明 单独列出。
open()
、io.open()
、codecs.open()
和fileinput.FileInput
不再接受文件模式中的'U'
(“通用换行符”)。在 Python 3 中,只要文件以文本模式打开,就默认使用“通用换行符”模式,并且'U'
标志自 Python 3.3 起已被弃用。这些函数的 newline 参数 控制通用换行符的工作方式。(由 Victor Stinner 在 bpo-37330 中贡献。)ast.AST
节点位置现在在提供给compile()
和其他相关函数时进行验证。如果检测到无效位置,将引发ValueError
。(由 Pablo Galindo 在 gh-93351 中贡献)在 Python 3.8 中弃用后,禁止将非
concurrent.futures.ThreadPoolExecutor
执行器传递给asyncio.loop.set_default_executor()
。(由 Illia Volochii 在 bpo-43234 中贡献。)calendar
:calendar.LocaleTextCalendar
和calendar.LocaleHTMLCalendar
类现在在未指定区域设置时使用locale.getlocale()
,而不是使用locale.getdefaultlocale()
。(由 Victor Stinner 在 bpo-46659 中贡献。)pdb
模块现在使用'UTF-8'
编码读取.pdbrc
配置文件。(由 Srinivas Reddy Thatiparthy (శ్రీనివాస్ రెడ్డి తాటిపర్తి) 在 bpo-41137 中贡献。)random.sample()
的 population 参数必须是一个序列,不再支持将set
自动转换为list
。此外,如果样本大小大于总体大小,将引发ValueError
。(由 Raymond Hettinger 在 bpo-40465 中贡献。)移除了
random.shuffle()
的 random 可选参数。它以前是用于洗牌的任意随机函数;现在,将始终使用random.random()
(其先前的默认值)。在
re
正则表达式语法 中,全局内联标志(例如(?i)
)现在只能在正则表达式的开头使用。在其他地方使用它们自 Python 3.6 起已被弃用。(由 Serhiy Storchaka 在 bpo-47066 中贡献。)在
re
模块中,修复了几个长期存在的 bug,这些 bug 在极少数情况下可能导致捕获组得到错误的结果。因此,这可能会改变这些情况下的捕获输出。(由 Ma Lin 在 bpo-35859 中贡献。)
构建更改¶
CPython 现在对 WebAssembly 平台 Emscripten (
wasm32-unknown-emscripten
,即浏览器中的 Python) 和 WebAssembly 系统接口 (WASI) (wasm32-unknown-wasi
) 具有 PEP 11 Tier 3 支持 的交叉编译功能。此工作受到 Pyodide 等先前工作的启发。这些平台提供了 POSIX API 的有限子集;与网络、进程、线程、信号、mmap 和用户/组相关的 Python 标准库功能和模块不可用或不起作用。(Emscripten 由 Christian Heimes 和 Ethan Smith 在 gh-84461 中贡献,WASI 由 Christian Heimes 在 gh-90473 中贡献;平台在 gh-95085 中得到推广)构建 CPython 现在需要
已移除
Py_NO_NAN
宏。由于 CPython 现在需要 IEEE 754 浮点数,因此 NaN 值始终可用。(由 Victor Stinner 在 bpo-46656 中贡献。)tkinter
包现在需要 Tcl/Tk 8.5.12 或更高版本。(由 Serhiy Storchaka 在 bpo-46996 中贡献。)大多数 stdlib 扩展模块的构建依赖项、编译器标志和链接器标志现在由 configure 检测。libffi、libnsl、libsqlite3、zlib、bzip2、liblzma、libcrypt、Tcl/Tk 和 uuid 标志由 pkg-config(如果可用)检测。
tkinter
现在需要 pkg-config 命令来检测 Tcl/Tk 头文件和库的开发设置。(由 Christian Heimes 和 Erlend Egeberg Aasland 在 bpo-45847、bpo-45747 和 bpo-45763 中贡献。)libpython 不再链接 libcrypt。(由 Mike Gilbert 在 bpo-45433 中贡献。)
CPython 现在可以通过向
--with-lto
传递thin
选项,即--with-lto=thin
,来使用 ThinLTO 选项构建。(由 Donghee Na 和 Brett Holman 在 bpo-44340 中贡献。)现在可以禁用对象结构的空闲列表。新的 configure 选项
--without-freelists
可用于禁用除空元组单例之外的所有空闲列表。(由 Christian Heimes 在 bpo-45522 中贡献。)Modules/Setup
和Modules/makesetup
已得到改进和整合。现在可以通过makesetup
构建扩展模块。除了一些测试模块外,所有模块都可以静态链接到主二进制文件或库中。(由 Brett Cannon 和 Christian Heimes 在 bpo-45548、bpo-45570、bpo-45571 和 bpo-43974 中贡献。)备注
使用环境变量
TCLTK_CFLAGS
和TCLTK_LIBS
手动指定 Tcl/Tk 头文件和库的位置。configure 选项--with-tcltk-includes
和--with-tcltk-libs
已被移除。在 RHEL 7 和 CentOS 7 上,开发包不提供
tcl.pc
和tk.pc
;请使用TCLTK_LIBS="-ltk8.5 -ltkstub8.5 -ltcl8.5"
。目录Misc/rhel7
包含.pc
文件以及如何使用 RHEL 7 和 CentOS 7 的 Tcl/Tk 和 OpenSSL 构建 Python 的说明。CPython 现在默认将对 Python
int
实现使用 30 位数字。此前,默认是在SIZEOF_VOID_P >= 8
的平台上使用 30 位数字,否则使用 15 位数字。仍然可以通过配置脚本的--enable-big-digits
选项或(对于 Windows)PC/pyconfig.h
中的PYLONG_BITS_IN_DIGIT
变量显式请求使用 15 位数字,但此选项可能会在未来的某个时候移除。(由 Mark Dickinson 在 bpo-45569 中贡献。)
C API 更改¶
新功能¶
添加了一个新的
PyType_GetName()
函数以获取类型的短名称。(由 Hai Shi 在 bpo-42035 中贡献。)添加了一个新的
PyType_GetQualName()
函数以获取类型的限定名称。(由 Hai Shi 在 bpo-42035 中贡献。)为受限 C API 添加了新的
PyThreadState_EnterTracing()
和PyThreadState_LeaveTracing()
函数,用于暂停和恢复跟踪和性能分析。(由 Victor Stinner 在 bpo-43760 中贡献。)添加了
Py_Version
常量,其值与PY_VERSION_HEX
相同。(由 Gabriele N. Tornetta 在 bpo-43931 中贡献。)Py_buffer
和 API 现在是受限 API 和稳定 ABI 的一部分bf_getbuffer
和bf_releasebuffer
类型槽
(由 Christian Heimes 在 bpo-45459 中贡献。)
添加了
PyType_GetModuleByDef()
函数,用于在无法直接获取此信息(通过PyCMethod
)的情况下,获取定义方法的模块。(由 Petr Viktorin 在 bpo-46613 中贡献。)添加了新的函数以打包和解包 C double(序列化和反序列化):
PyFloat_Pack2()
、PyFloat_Pack4()
、PyFloat_Pack8()
、PyFloat_Unpack2()
、PyFloat_Unpack4()
和PyFloat_Unpack8()
。(由 Victor Stinner 在 bpo-46906 中贡献。)添加了新的函数来获取帧对象属性:
PyFrame_GetBuiltins()
、PyFrame_GetGenerator()
、PyFrame_GetGlobals()
、PyFrame_GetLasti()
。添加了两个新函数来获取和设置当前活动异常实例:
PyErr_GetHandledException()
和PyErr_SetHandledException()
。它们是PyErr_SetExcInfo()
和PyErr_GetExcInfo()
的替代品,后者使用旧的异常三元组表示。(由 Irit Katriel 在 bpo-46343 中贡献。)添加了
PyConfig.safe_path
成员。(由 Victor Stinner 在 gh-57684 中贡献。)
移植到 Python 3.11¶
一些宏已转换为静态内联函数,以避免 宏陷阱。此更改对用户而言应基本透明,因为替换函数将把其参数转换为预期类型,以避免由于静态类型检查导致的编译器警告。然而,当受限 C API 设置为 >=3.11 时,这些转换不会进行,调用者需要将参数转换为预期类型。有关更多详细信息,请参阅 PEP 670。(由 Victor Stinner 和 Erlend E. Aasland 在 gh-89653 中贡献。)
PyErr_SetExcInfo()
不再使用type
和traceback
参数,解释器现在从异常实例(value
参数)派生这些值。该函数仍然窃取所有三个参数的引用。(由 Irit Katriel 在 bpo-45711 中贡献。)PyErr_GetExcInfo()
现在从异常实例(value
字段)派生结果的type
和traceback
字段。(由 Irit Katriel 在 bpo-45711 中贡献。)_frozen
有一个新的is_package
字段,用于指示冻结模块是否为包。此前,size
字段中的负值是指示符。现在size
将只使用非负值。(由 Kumar Aditya 在 bpo-46608 中贡献。)_PyFrameEvalFunction()
现在将其第二个参数从PyFrameObject*
改为_PyInterpreterFrame*
。有关如何使用此函数指针类型的更多详细信息,请参阅 PEP 523。PyCode_New()
和PyCode_NewWithPosOnlyArgs()
现在接受一个额外的exception_table
参数。应尽可能避免使用这些函数。要获取自定义代码对象:使用编译器创建一个代码对象,然后使用replace
方法获取修改后的版本。PyCodeObject
不再有co_code
、co_varnames
、co_cellvars
和co_freevars
字段。请改用PyCode_GetCode()
、PyCode_GetVarnames()
、PyCode_GetCellvars()
和PyCode_GetFreevars()
分别通过 C API 访问它们。(由 Brandt Bucher 在 bpo-46841 和 Ken Jin 在 gh-92154 和 gh-94936 中贡献。)旧的垃圾桶宏 (
Py_TRASHCAN_SAFE_BEGIN
/Py_TRASHCAN_SAFE_END
) 现已弃用。它们应替换为新的宏Py_TRASHCAN_BEGIN
和Py_TRASHCAN_END
。一个具有旧宏的 tp_dealloc 函数,例如
static void mytype_dealloc(mytype *p) { PyObject_GC_UnTrack(p); Py_TRASHCAN_SAFE_BEGIN(p); ... Py_TRASHCAN_SAFE_END }
应按如下方式迁移到新宏
static void mytype_dealloc(mytype *p) { PyObject_GC_UnTrack(p); Py_TRASHCAN_BEGIN(p, mytype_dealloc) ... Py_TRASHCAN_END }
请注意,
Py_TRASHCAN_BEGIN
有一个第二个参数,它应该是它所在的解除分配函数。为了在相同的代码库中支持旧的 Python 版本,您可以定义以下宏并在整个代码中使用它们(鸣谢:这些是从
mypy
代码库复制的)#if PY_VERSION_HEX >= 0x03080000 # define CPy_TRASHCAN_BEGIN(op, dealloc) Py_TRASHCAN_BEGIN(op, dealloc) # define CPy_TRASHCAN_END(op) Py_TRASHCAN_END #else # define CPy_TRASHCAN_BEGIN(op, dealloc) Py_TRASHCAN_SAFE_BEGIN(op) # define CPy_TRASHCAN_END(op) Py_TRASHCAN_SAFE_END(op) #endif
如果类型定义时设置了
Py_TPFLAGS_HAVE_GC
标志但没有遍历函数(PyTypeObject.tp_traverse
),PyType_Ready()
函数现在会引发错误。(由 Victor Stinner 在 bpo-44263 中贡献。)具有
Py_TPFLAGS_IMMUTABLETYPE
标志的堆类型现在可以继承 PEP 590 vectorcall 协议。此前,这仅适用于 静态类型。(由 Erlend E. Aasland 在 bpo-43908 中贡献)由于
Py_TYPE()
已更改为内联静态函数,Py_TYPE(obj) = new_type
必须替换为Py_SET_TYPE(obj, new_type)
:请参阅Py_SET_TYPE()
函数(自 Python 3.9 起可用)。为了向后兼容,可以使用此宏#if PY_VERSION_HEX < 0x030900A4 && !defined(Py_SET_TYPE) static inline void _Py_SET_TYPE(PyObject *ob, PyTypeObject *type) { ob->ob_type = type; } #define Py_SET_TYPE(ob, type) _Py_SET_TYPE((PyObject*)(ob), type) #endif
(由 Victor Stinner 在 bpo-39573 中贡献。)
由于
Py_SIZE()
已更改为内联静态函数,Py_SIZE(obj) = new_size
必须替换为Py_SET_SIZE(obj, new_size)
:请参阅Py_SET_SIZE()
函数(自 Python 3.9 起可用)。为了向后兼容,可以使用此宏#if PY_VERSION_HEX < 0x030900A4 && !defined(Py_SET_SIZE) static inline void _Py_SET_SIZE(PyVarObject *ob, Py_ssize_t size) { ob->ob_size = size; } #define Py_SET_SIZE(ob, size) _Py_SET_SIZE((PyVarObject*)(ob), size) #endif
(由 Victor Stinner 在 bpo-39573 中贡献。)
当
Py_LIMITED_API
宏设置为0x030b0000
(Python 3.11) 或更高版本时,<Python.h>
不再包含头文件<stdlib.h>
、<stdio.h>
、<errno.h>
和<string.h>
。C 扩展应在#include <Python.h>
之后显式包含这些头文件。(由 Victor Stinner 在 bpo-45434 中贡献。)非受限 API 文件
cellobject.h
、classobject.h
、code.h
、context.h
、funcobject.h
、genobject.h
和longintrepr.h
已移至Include/cpython
目录。此外,eval.h
头文件已被移除。这些文件不应直接包含,因为它们已包含在Python.h
中:包含文件。如果已直接包含它们,请考虑改用Python.h
。(由 Victor Stinner 在 bpo-35134 中贡献。)PyUnicode_CHECK_INTERNED()
宏已从受限 C API 中排除。它在那里从未可用,因为它使用了受限 C API 中不可用的内部结构。(由 Victor Stinner 在 bpo-46007 中贡献。)以下帧函数和类型现在可直接通过
#include <Python.h>
使用,不再需要添加#include <frameobject.h>
(由 Victor Stinner 在 gh-93937 中贡献。)
PyFrameObject
结构成员已从公共 C API 中移除。虽然文档指出
PyFrameObject
字段可能随时更改,但它们已稳定很长时间,并被一些流行的扩展使用。在 Python 3.11 中,帧结构被重组以实现性能优化。一些字段完全移除,因为它们是旧实现中的细节。
f_back
:使用PyFrame_GetBack()
。f_blockstack
:已移除。f_builtins
:使用PyFrame_GetBuiltins()
。f_code
:使用PyFrame_GetCode()
。f_gen
:使用PyFrame_GetGenerator()
。f_globals
:使用PyFrame_GetGlobals()
。f_iblock
:已移除。f_lasti
:使用PyFrame_GetLasti()
。使用PyCode_Addr2Line()
的代码应改用PyFrame_GetLineNumber()
;它可能更快。f_lineno
:使用PyFrame_GetLineNumber()
f_locals
:使用PyFrame_GetLocals()
。f_stackdepth
:已移除。f_state
:无公共 API(重命名为f_frame.f_state
)。f_trace
:无公共 API。f_trace_lines
:使用PyObject_GetAttrString((PyObject*)frame, "f_trace_lines")
。f_trace_opcodes
:使用PyObject_GetAttrString((PyObject*)frame, "f_trace_opcodes")
。f_localsplus
:无公共 API(重命名为f_frame.localsplus
)。f_valuestack
:已移除。
Python 帧对象现在是惰性创建的。一个副作用是
f_back
成员不应直接访问,因为它的值现在也是惰性计算的。必须调用PyFrame_GetBack()
函数。直接访问
f_locals
的调试器 必须 调用PyFrame_GetLocals()
。它们不再需要调用PyFrame_FastToLocalsWithError()
或PyFrame_LocalsToFast()
,实际上它们不应该调用这些函数。帧的必要更新现在由虚拟机管理。在 Python 3.8 及更早版本上定义
PyFrame_GetCode()
的代码#if PY_VERSION_HEX < 0x030900B1 static inline PyCodeObject* PyFrame_GetCode(PyFrameObject *frame) { Py_INCREF(frame->f_code); return frame->f_code; } #endif
在 Python 3.8 及更早版本上定义
PyFrame_GetBack()
的代码#if PY_VERSION_HEX < 0x030900B1 static inline PyFrameObject* PyFrame_GetBack(PyFrameObject *frame) { Py_XINCREF(frame->f_back); return frame->f_back; } #endif
或者使用 pythoncapi_compat 项目 在旧版 Python 上获取这两个函数。
PyThreadState
结构成员的更改frame
:已移除,请使用PyThreadState_GetFrame()
(该函数在 bpo-40429 中添加到 Python 3.9)。警告:该函数返回 强引用,需要调用Py_XDECREF()
。tracing
:已更改,请使用PyThreadState_EnterTracing()
和PyThreadState_LeaveTracing()
(这些函数在 bpo-43760 中添加到 Python 3.11)。recursion_depth
:已移除,请改用(tstate->recursion_limit - tstate->recursion_remaining)
。stackcheck_counter
:已移除。
在 Python 3.8 及更早版本上定义
PyThreadState_GetFrame()
的代码#if PY_VERSION_HEX < 0x030900B1 static inline PyFrameObject* PyThreadState_GetFrame(PyThreadState *tstate) { Py_XINCREF(tstate->frame); return tstate->frame; } #endif
在 Python 3.10 及更早版本上定义
PyThreadState_EnterTracing()
和PyThreadState_LeaveTracing()
的代码#if PY_VERSION_HEX < 0x030B00A2 static inline void PyThreadState_EnterTracing(PyThreadState *tstate) { tstate->tracing++; #if PY_VERSION_HEX >= 0x030A00A1 tstate->cframe->use_tracing = 0; #else tstate->use_tracing = 0; #endif } static inline void PyThreadState_LeaveTracing(PyThreadState *tstate) { int use_tracing = (tstate->c_tracefunc != NULL || tstate->c_profilefunc != NULL); tstate->tracing--; #if PY_VERSION_HEX >= 0x030A00A1 tstate->cframe->use_tracing = use_tracing; #else tstate->use_tracing = use_tracing; #endif } #endif
或者使用 pythoncapi-compat 项目 在旧版 Python 上获取这些函数。
鼓励分发商使用优化的 Blake2 库 libb2 构建 Python。
PyConfig.module_search_paths_set
字段现在必须设置为 1,以便初始化使用PyConfig.module_search_paths
初始化sys.path
。否则,初始化将重新计算路径并替换添加到module_search_paths
的任何值。PyConfig_Read()
不再计算初始搜索路径,也不会填充任何值到PyConfig.module_search_paths
。要计算默认路径并进行修改,请完成初始化并使用PySys_GetObject()
将sys.path
作为 Python 列表对象检索并直接修改它。
已弃用¶
弃用以下函数以配置 Python 初始化
PySys_AddWarnOptionUnicode()
PySys_AddWarnOption()
PySys_AddXOption()
PySys_HasWarnOptions()
PySys_SetArgvEx()
PySys_SetArgv()
PySys_SetPath()
Py_SetPath()
Py_SetProgramName()
Py_SetPythonHome()
Py_SetStandardStreamEncoding()
_Py_SetProgramFullPath()
请改用 Python 初始化配置 的新
PyConfig
API(PEP 587)。(由 Victor Stinner 在 gh-88279 中贡献。)弃用
PyBytesObject
的ob_shash
成员。请改用PyObject_Hash()
。(由 Inada Naoki 在 bpo-46864 中贡献。)
Python 3.12 中待移除¶
以下 C API 已在早期的 Python 版本中弃用,并将在 Python 3.12 中移除。
PyUnicode_AS_DATA()
PyUnicode_AS_UNICODE()
PyUnicode_AsUnicodeAndSize()
PyUnicode_AsUnicode()
PyUnicode_FromUnicode()
PyUnicode_GET_DATA_SIZE()
PyUnicode_GET_SIZE()
PyUnicode_GetSize()
PyUnicode_IS_COMPACT()
PyUnicode_IS_READY()
PyUnicode_WSTR_LENGTH()
_PyUnicode_AsUnicode()
PyUnicode_WCHAR_KIND
PyUnicode_InternImmortal()
已移除¶
PyFrame_BlockSetup()
和PyFrame_BlockPop()
已被移除。(由 Mark Shannon 在 bpo-40222 中贡献。)移除以下使用
errno
变量的数学宏Py_ADJUST_ERANGE1()
Py_ADJUST_ERANGE2()
Py_OVERFLOWED()
Py_SET_ERANGE_IF_OVERFLOW()
Py_SET_ERRNO_ON_MATH_ERROR()
(由 Victor Stinner 在 bpo-45412 中贡献。)
移除
Py_UNICODE_COPY()
和Py_UNICODE_FILL()
宏,它们自 Python 3.3 起已被弃用。请改用PyUnicode_CopyCharacters()
或memcpy()
(wchar_t*
字符串),以及PyUnicode_Fill()
函数。(由 Victor Stinner 在 bpo-41123 中贡献。)移除
pystrhex.h
头文件。它只包含私有函数。C 扩展只应包含主要的<Python.h>
头文件。(由 Victor Stinner 在 bpo-45434 中贡献。)移除
Py_FORCE_DOUBLE()
宏。它曾被Py_IS_INFINITY()
宏使用。(由 Victor Stinner 在 bpo-45440 中贡献。)当
Py_LIMITED_API
定义时,以下项目不再可用Py_MARSHAL_VERSION
宏
这些不属于 受限 API。
(由 Victor Stinner 在 bpo-45474 中贡献。)
从受限 C API 中排除
PyWeakref_GET_OBJECT()
。它从未起作用,因为PyWeakReference
结构在受限 C API 中是不透明的。(由 Victor Stinner 在 bpo-35134 中贡献。)移除
PyHeapType_GET_MEMBERS()
宏。它因错误地暴露在公共 C API 中,它只能在 Python 内部使用。请改用PyTypeObject.tp_members
成员。(由 Victor Stinner 在 bpo-40170 中贡献。)移除
HAVE_PY_SET_53BIT_PRECISION
宏(已移至内部 C API)。(由 Victor Stinner 在 bpo-45412 中贡献。)
移除
Py_UNICODE
编码器 API,因为它们自 Python 3.3 起已被弃用,使用较少且相对于推荐的替代方案效率低下。已移除的函数有:
PyUnicode_Encode()
PyUnicode_EncodeASCII()
PyUnicode_EncodeLatin1()
PyUnicode_EncodeUTF7()
PyUnicode_EncodeUTF8()
PyUnicode_EncodeUTF16()
PyUnicode_EncodeUTF32()
PyUnicode_EncodeUnicodeEscape()
PyUnicode_EncodeRawUnicodeEscape()
PyUnicode_EncodeCharmap()
PyUnicode_TranslateCharmap()
PyUnicode_EncodeDecimal()
PyUnicode_TransformDecimalToASCII()
3.11.4 中的显著更改¶
tarfile¶
tarfile
中的提取方法和shutil.unpack_archive()
现在有一个新的 filter 参数,允许限制 tar 功能,这些功能可能令人意外或危险,例如在目标目录之外创建文件。有关详细信息,请参阅 提取过滤器。在 Python 3.12 中,不带 filter 参数的使用将显示DeprecationWarning
。在 Python 3.14 中,默认值将切换为'data'
。(由 Petr Viktorin 在 PEP 706 中贡献。)
3.11.5 中的显著更改¶
OpenSSL¶
python.org 提供的 Windows 构建和 macOS 安装程序现在使用 OpenSSL 3.0。