Python 3.9 新特性

编辑:

Łukasz Langa

本文介绍了 Python 3.9 相对于 3.8 的新特性。 Python 3.9 于 2020 年 10 月 5 日发布。有关完整详细信息,请参阅更新日志

参见

PEP 596 - Python 3.9 发布计划

摘要 – 版本亮点

新的语法特性

  • PEP 584,将联合运算符添加到 dict

  • PEP 585,标准集合中的类型提示泛型;

  • PEP 614,放宽了对装饰器的语法限制。

新的内置特性

  • PEP 616,用于删除前缀和后缀的字符串方法。

标准库中的新特性

  • PEP 593,灵活的函数和变量注释;

  • 添加了os.pidfd_open(),它允许在没有竞争和信号的情况下进行进程管理。

解释器改进

  • PEP 573,从 C 扩展类型的方法快速访问模块状态;

  • PEP 617,CPython 现在使用基于 PEG 的新解析器;

  • 许多 Python 内置函数(range、tuple、set、frozenset、list、dict)现在使用 PEP 590 vectorcall 加速;

  • 垃圾回收不再阻塞复活的对象;

  • 许多 Python 模块(_abcaudioop_bz2_codecs_contextvars_crypt_functools_json_localemathoperatorresourcetime_weakref) 现在使用 PEP 489 定义的多阶段初始化;

  • 许多标准库模块 (audioopastgrp_hashlibpwd_posixsubprocessrandomselectstructtermioszlib) 现在使用 PEP 384 定义的稳定 ABI。

新的库模块

  • PEP 615,IANA 时区数据库现在以 zoneinfo 模块的形式存在于标准库中;

  • 现在在新的graphlib模块中提供了图的拓扑排序的实现。

发布过程变更

  • PEP 602,CPython 采用年度发布周期。

您应该检查代码中的 DeprecationWarning

当 Python 2.7 仍然受支持时,Python 3 中的许多功能都保留了与 Python 2.7 的向后兼容性。 随着 Python 2 支持的结束,这些向后兼容性层已被删除,或将很快被删除。 它们中的大多数都发出了DeprecationWarning警告多年。 例如,使用 collections.Mapping 而不是 collections.abc.Mapping 会发出 DeprecationWarning 自 2012 年发布的 Python 3.3 起。

使用 -W default 命令行选项测试你的应用程序,查看 DeprecationWarningPendingDeprecationWarning,或者甚至使用 -W error 将它们视为错误。 警告过滤器 可以用来忽略来自第三方代码的警告。

Python 3.9 是提供这些 Python 2 向后兼容层的最后一个版本,为的是给 Python 项目维护者更多时间来组织移除 Python 2 的支持,并添加对 Python 3.9 的支持。

为了向后兼容,在 collections 模块中,抽象基类 的别名,例如 collections.Mappingcollections.abc.Mapping 的别名,会保留最后一个版本。 它们将从 Python 3.10 中删除。

更普遍来说,尝试在 Python 开发模式 下运行你的测试,这有助于使你的代码与下一个 Python 版本兼容。

注意:在此版本的 Python 中,还删除了一些预先存在的弃用。请查阅 已删除 部分。

新功能

字典合并和更新运算符

合并(|)和更新(|=)运算符已添加到内置的 dict 类中。这些是对现有的 dict.update{**d1, **d2} 合并字典方法的补充。

示例

>>> x = {"key1": "value1 from x", "key2": "value2 from x"}
>>> y = {"key2": "value2 from y", "key3": "value3 from y"}
>>> x | y
{'key1': 'value1 from x', 'key2': 'value2 from y', 'key3': 'value3 from y'}
>>> y | x
{'key2': 'value2 from x', 'key3': 'value3 from y', 'key1': 'value1 from x'}

有关完整说明,请参阅 PEP 584。(由 Brandt Bucher 在 bpo-36144 中贡献。)

删除前缀和后缀的新字符串方法

添加了 str.removeprefix(prefix)str.removesuffix(suffix),以便轻松地从字符串中删除不需要的前缀或后缀。还添加了相应的 bytesbytearraycollections.UserString 方法。 有关完整说明,请参阅 PEP 616。(由 Dennis Sweeney 在 bpo-39939 中贡献。)

标准集合中的类型提示泛型

在类型注解中,你现在可以使用内置集合类型(如 listdict)作为泛型类型,而不是从 typing 导入相应的大写类型(例如 ListDict)。 标准库中的一些其他类型现在也是泛型的,例如 queue.Queue

示例

def greet_all(names: list[str]) -> None:
    for name in names:
        print("Hello", name)

有关更多详细信息,请参阅 PEP 585。(由 Guido van Rossum、Ethan Smith 和 Batuhan Taşkaya 在 bpo-39481 中贡献。)

新解析器

Python 3.9 使用基于 PEG 而不是 LL(1) 的新解析器。 新解析器的性能与旧解析器大致相当,但在设计新语言功能时,PEG 形式比 LL(1) 更灵活。 我们将在 Python 3.10 及更高版本中开始使用此灵活性。

ast 模块使用新解析器,并生成与旧解析器相同的 AST。

在 Python 3.10 中,旧解析器将被删除,所有依赖于它的功能(主要是 parser 模块,它早已被弃用)也将被删除。 在 Python 3.9 中,你可以使用命令行开关(-X oldparser)或环境变量(PYTHONOLDPARSER=1)切换回 LL(1) 解析器。

有关更多详细信息,请参阅 PEP 617。(由 Guido van Rossum、Pablo Galindo 和 Lysandros Nikolaou 在 bpo-40334 中贡献。)

其他语言更改

  • __import__() 现在会引发 ImportError 而不是 ValueError,后者曾经在相对导入超出其顶层包时发生。(由 Ngalim Siregar 在 bpo-37444 中贡献。)

  • Python 现在获取命令行上指定的脚本文件名的绝对路径(例如:python3 script.py):__main__ 模块的 __file__ 属性变为绝对路径,而不是相对路径。 这些路径在当前目录被 os.chdir() 更改后仍然有效。 作为副作用,在这种情况下,回溯也会显示 __main__ 模块帧的绝对路径。(由 Victor Stinner 在 bpo-20443 中贡献。)

  • Python 开发模式调试构建 中,现在会检查 *encoding* 和 *errors* 参数的字符串编码和解码操作。 示例:open()str.encode()bytes.decode()

    默认情况下,为了获得最佳性能,仅在第一次编码/解码错误时检查 *errors* 参数,并且有时会忽略空字符串的 *encoding* 参数。(由 Victor Stinner 在 bpo-37388 中贡献。)

  • 对于所有非零的 n"".replace("", s, n) 现在返回 s 而不是空字符串。 现在它与 "".replace("", s) 一致。 对于 bytesbytearray 对象也有类似的更改。(由 Serhiy Storchaka 在 bpo-28029 中贡献。)

  • 现在任何有效表达式都可以用作装饰器。 以前,语法限制要大得多。 有关详细信息,请参阅 PEP 614。(由 Brandt Bucher 在 bpo-39702 中贡献。)

  • 改进了 typing 模块的帮助。 现在会显示所有特殊形式和特殊泛型别名(例如 UnionList)的文档字符串。 将 help() 与诸如 List[int] 之类的泛型别名一起使用将显示相应具体类型(在这种情况下为 list)的帮助。(由 Serhiy Storchaka 在 bpo-40257 中贡献。)

  • 现在禁止并行运行 aclose() / asend() / athrow(),并且 ag_running 现在反映异步生成器的实际运行状态。(由 Yury Selivanov 在 bpo-30773 中贡献。)

  • in 运算符和 contains()indexOf()countOf() 函数中,调用 __iter__ 方法时发生的意外错误不再被 TypeError 掩盖。operator 模块。(由 Serhiy Storchaka 在 bpo-40824 中贡献。)

  • 未加括号的 lambda 表达式不再能作为推导式和生成器表达式中 if 子句的表达式部分。详细信息请参见 bpo-41848bpo-43755

新模块

zoneinfo

zoneinfo 模块为标准库带来了对 IANA 时区数据库的支持。 它添加了 zoneinfo.ZoneInfo,这是一个具体的 datetime.tzinfo 实现,其背后是系统的时区数据。

示例

>>> from zoneinfo import ZoneInfo
>>> from datetime import datetime, timedelta

>>> # Daylight saving time
>>> dt = datetime(2020, 10, 31, 12, tzinfo=ZoneInfo("America/Los_Angeles"))
>>> print(dt)
2020-10-31 12:00:00-07:00
>>> dt.tzname()
'PDT'

>>> # Standard time
>>> dt += timedelta(days=7)
>>> print(dt)
2020-11-07 12:00:00-08:00
>>> print(dt.tzname())
PST

作为不提供 IANA 数据库的平台的备用数据源,tzdata 模块已作为第一方软件包发布 - 通过 PyPI 分发并由 CPython 核心团队维护。

参见

PEP 615 – 标准库中对 IANA 时区数据库的支持

由 Paul Ganssle 编写和实现 PEP

graphlib

添加了一个新模块 graphlib,其中包含 graphlib.TopologicalSorter 类,该类提供对图执行拓扑排序的功能。(由 Pablo Galindo、Tim Peters 和 Larry Hastings 在 bpo-17005 中贡献。)

改进的模块

ast

dump() 添加了 *indent* 选项,该选项允许生成多行缩进输出。(由 Serhiy Storchaka 在 bpo-37995 中贡献。)

ast 模块中添加了 ast.unparse() 函数,该函数可用于反解析 ast.AST 对象,并生成一个字符串,其中包含的代码在解析时会产生等效的 ast.AST 对象。(由 Pablo Galindo 和 Batuhan Taskaya 在 bpo-38870 中贡献。)

向 AST 节点添加了文档字符串,其中包含用于构造该节点的 ASDL 签名。(由 Batuhan Taskaya 在 bpo-39638 中贡献。)

asyncio

由于重大的安全问题,不再支持 asyncio.loop.create_datagram_endpoint() 的 *reuse_address* 参数。这是因为 UDP 中套接字选项 SO_REUSEADDR 的行为。有关更多详细信息,请参阅 loop.create_datagram_endpoint() 的文档。(由 Kyle Stanley、Antoine Pitrou 和 Yury Selivanov 在 bpo-37228 中贡献。)

添加了一个新的 协程 shutdown_default_executor(),它计划关闭默认执行器,并等待 ThreadPoolExecutor 完成关闭。此外,asyncio.run() 已更新为使用新的 协程。(由 Kyle Stanley 在 bpo-34037 中贡献。)

添加了 asyncio.PidfdChildWatcher,这是一种特定于 Linux 的子进程监视器实现,用于轮询进程文件描述符。(bpo-38692

添加了一个新的 协程 asyncio.to_thread()。它主要用于在单独的线程中运行 IO 绑定函数,以避免阻塞事件循环,并且基本上作为 run_in_executor() 的高级版本工作,可以直接使用关键字参数。(由 Kyle Stanley 和 Yury Selivanov 在 bpo-32309 中贡献。)

当由于超时而取消任务时,asyncio.wait_for() 现在将等待取消完成,即使在 *timeout* <= 0 的情况下,就像使用正超时一样。(由 Elvis Pranskevichus 在 bpo-32751 中贡献。)

当使用 ssl.SSLSocket 套接字调用不兼容的方法时,asyncio 现在会引发 TypeError。(由 Ido Michael 在 bpo-37404 中贡献。)

compileall

添加了使用硬链接复制重复 .pyc 文件的新可能性:*hardlink_dupes* 参数和 –hardlink-dupes 命令行选项。(由 Lumír ‘Frenzy’ Balhar 在 bpo-40495 中贡献。)

为生成的 .pyc 文件中的路径操作添加了新选项:*stripdir*、*prependdir*、*limit_sl_dest* 参数和 -s、-p、-e 命令行选项。 添加了多次指定优化级别选项的可能性。(由 Lumír ‘Frenzy’ Balhar 在 bpo-38112 中贡献。)

concurrent.futures

concurrent.futures.Executor.shutdown() 添加了一个新的 cancel_futures 参数,该参数会取消所有尚未开始运行的待处理 future,而不是等待它们完成才关闭执行器。(由 Kyle Stanley 在 bpo-39349 中贡献。)

ThreadPoolExecutorProcessPoolExecutor 中移除了守护线程。这提高了与子解释器的兼容性,并提高了它们关闭过程的可预测性。(由 Kyle Stanley 在 bpo-39812 中贡献。)

现在,只有在没有可重用的空闲 worker 时,才会按需生成 ProcessPoolExecutor 中的 worker。这优化了启动开销,并减少了空闲 worker 造成的 CPU 时间浪费。(由 Kyle Stanley 在 bpo-39207 中贡献。)

curses

添加了 curses.get_escdelay()curses.set_escdelay()curses.get_tabsize()curses.set_tabsize() 函数。(由 Anthony Sottile 在 bpo-38312 中贡献。)

datetime

isocalendar() 方法(针对 datetime.date)和 isocalendar() 方法(针对 datetime.datetime)现在返回 namedtuple(),而不是 tuple。(由 Donghee Na 在 bpo-24416 中贡献。)

distutils

upload 命令现在创建 SHA2-256 和 Blake2b-256 哈希摘要。它会在阻止 MD5 摘要的平台上跳过 MD5。(由 Christian Heimes 在 bpo-40698 中贡献。)

fcntl

添加了常量 F_OFD_GETLKF_OFD_SETLKF_OFD_SETLKW。(由 Donghee Na 在 bpo-38602 中贡献。)

ftplib

如果为构造函数提供的超时时间为零,FTPFTP_TLS 现在会引发 ValueError,以防止创建非阻塞套接字。(由 Donghee Na 在 bpo-39259 中贡献。)

gc

当垃圾收集器进行一次收集时,其中一些对象复活(在执行 finalizer 之后,可以从隔离的周期外部访问它们),不要阻止收集所有仍然无法访问的对象。(由 Pablo Galindo 和 Tim Peters 在 bpo-38379 中贡献。)

添加了一个新函数 gc.is_finalized(),用于检查对象是否已由垃圾收集器最终确定。(由 Pablo Galindo 在 bpo-39322 中贡献。)

hashlib

现在,hashlib 模块可以在可用时使用 OpenSSL 中的 SHA3 哈希和 SHAKE XOF。(由 Christian Heimes 在 bpo-37630 中贡献。)

现在可以使用 ./configure --without-builtin-hashlib-hashes 禁用内置哈希模块,或使用例如 ./configure --with-builtin-hashlib-hashes=sha3,blake2 选择性地启用内置哈希模块,以强制使用基于 OpenSSL 的实现。(由 Christian Heimes 在 bpo-40479 中贡献。)

http

HTTP 状态代码 103 EARLY_HINTS418 IM_A_TEAPOT425 TOO_EARLY 已添加到 http.HTTPStatus 中。(由 Donghee Na 在 bpo-39509 中贡献,Ross Rhodes 在 bpo-39507 中贡献。)

IDLE 和 idlelib

添加了关闭光标闪烁的选项。(由 Zackery Spytz 在 bpo-4603 中贡献。)

现在,按 Esc 键会关闭 IDLE 完成窗口。(由 Johnny Najera 在 bpo-38944 中贡献。)

向模块名称完成列表中添加了关键字。(由 Terry J. Reedy 在 bpo-37765 中贡献。)

3.9 维护版本中的新增功能

使 IDLE 调用 sys.excepthook()(在不带“-n”的情况下启动时)。以前会忽略用户钩子。(由 Ken Hilton 在 bpo-43008 中贡献。)

以上更改已向后移植到 3.8 维护版本。

重新排列了设置对话框。将“常规”选项卡分为“窗口”和“Shell/Ed”选项卡。将扩展帮助菜单的帮助源移至“扩展”选项卡。为新选项腾出空间并缩短对话框。后者使对话框更好地适应小屏幕。(由 Terry Jan Reedy 在 bpo-40468 中贡献。)将缩进空间设置从“字体”选项卡移到新的“窗口”选项卡。(由 Mark Roseman 和 Terry Jan Reedy 在 bpo-33962 中贡献。)

将语法高亮应用于 .pyi 文件。(由 Alex Waygood 和 Terry Jan Reedy 在 bpo-45447 中贡献。)

imaplib

IMAP4IMAP4_SSL 现在在其构造函数中有一个可选的 timeout 参数。此外,open() 方法现在也进行了此更改,带有一个可选的 timeout 参数。IMAP4_SSLIMAP4_stream 的重写方法已应用此更改。(由 Donghee Na 在 bpo-38615 中贡献。)

添加了 imaplib.IMAP4.unselect()imaplib.IMAP4.unselect() 释放与所选邮箱关联的服务器资源,并将服务器返回到经过身份验证的状态。此命令执行的操作与 imaplib.IMAP4.close() 相同,只是不会从当前选定的邮箱中永久删除任何消息。(由 Donghee Na 在 bpo-40375 中贡献。)

importlib

为了提高与 import 语句的一致性,对于无效的相对导入尝试,importlib.util.resolve_name() 现在会引发 ImportError,而不是 ValueError。(由 Ngalim Siregar 在 bpo-37444 中贡献。)

发布不可变模块对象的导入加载器现在可以发布不可变的包以及单独的模块。(由 Dino Viehland 在 bpo-39336 中贡献。)

添加了 importlib.resources.files() 函数,支持包数据中的子目录,与 importlib_resources 1.5 版本的向后移植相匹配。(由 Jason R. Coombs 在 bpo-39791 中贡献。)

importlib_metadata 1.6.1 版本更新了 importlib.metadata

inspect

inspect.BoundArguments.argumentsOrderedDict 更改为常规字典。(由 Inada Naoki 在 bpo-36350bpo-39775 中贡献。)

ipaddress

ipaddress 现在支持 IPv6 作用域地址(带有后缀 %<scope_id> 的 IPv6 地址)。

可以使用 ipaddress.IPv6Address 解析作用域 IPv6 地址。如果存在,作用域区域 ID 可以通过 scope_id 属性获得。(由 Oleksandr Pavliuk 在 bpo-34788 中贡献。)

从 Python 3.9.5 开始,ipaddress 模块不再接受 IPv4 地址字符串中的任何前导零。(由 Christian Heimes 在 bpo-36384 中贡献。)

math

扩展了 math.gcd() 函数以处理多个参数。以前,它只支持两个参数。(由 Serhiy Storchaka 在 bpo-39648 中贡献。)

添加了 math.lcm():返回指定参数的最小公倍数。(由 Mark Dickinson、Ananthakrishnan 和 Serhiy Storchaka 在 bpo-39479bpo-39648 中贡献。)

添加了 math.nextafter():返回 x 之后朝向 y 的下一个浮点数值。(由 Victor Stinner 在 bpo-39288 中贡献。)

添加了 math.ulp():返回浮点数的最小有效位的值。(由 Victor Stinner 在 bpo-39310 中贡献。)

multiprocessing

multiprocessing.SimpleQueue 类有一个新的 close() 方法来显式关闭队列。(由 Victor Stinner 在 bpo-30966 中贡献。)

nntplib

NNTPNNTP_SSL 现在如果构造函数的给定超时时间为零,则会引发 ValueError,以防止创建非阻塞套接字。(由 Donghee Na 在 bpo-39259 中贡献。)

os

si_code 添加了 CLD_KILLEDCLD_STOPPED。(由 Donghee Na 在 bpo-38493 中贡献。)

公开了 Linux 特有的 os.pidfd_open() (bpo-38692) 和 os.P_PIDFD (bpo-38713),用于使用文件描述符进行进程管理。

os.unsetenv() 函数现在也可在 Windows 上使用。(由 Victor Stinner 在 bpo-39413 中贡献。)

os.putenv()os.unsetenv() 函数现在始终可用。(由 Victor Stinner 在 bpo-39395 中贡献。)

添加了 os.waitstatus_to_exitcode() 函数:将等待状态转换为退出代码。(由 Victor Stinner 在 bpo-40094 中贡献。)

pathlib

添加了 pathlib.Path.readlink(),其作用类似于 os.readlink()。(由 Girts Folkmanis 在 bpo-30618 中贡献。)

pdb

在 Windows 上,现在 Pdb 支持 ~/.pdbrc。(由 Tim Hopper 和 Dan Lidral-Porter 在 bpo-20523 中贡献。)

poplib

POP3POP3_SSL 现在如果构造函数的给定超时时间为零,则会引发 ValueError,以防止创建非阻塞套接字。(由 Donghee Na 在 bpo-39259 中贡献。)

pprint

pprint 现在可以漂亮地打印 types.SimpleNamespace。(由 Carl Bordum Hansen 在 bpo-37376 中贡献。)

pydoc

现在不仅为类、函数、方法等显示文档字符串,而且为任何具有自己的 __doc__ 属性的对象显示文档字符串。(由 Serhiy Storchaka 在 bpo-40257 中贡献。)

random

添加了一个新的 random.Random.randbytes 方法:生成随机字节。(由 Victor Stinner 在 bpo-40286 中贡献。)

signal

公开了 Linux 特有的 signal.pidfd_send_signal(),用于使用文件描述符而不是 pid 向进程发送信号。(bpo-38712

smtplib

SMTPSMTP_SSL 现在如果构造函数的给定超时时间为零,则会引发 ValueError,以防止创建非阻塞套接字。(由 Donghee Na 在 bpo-39259 中贡献。)

LMTP 构造函数现在有一个可选的 timeout 参数。(由 Donghee Na 在 bpo-39329 中贡献。)

socket

socket 模块现在在 Linux 4.1 及更高版本上导出 CAN_RAW_JOIN_FILTERS 常量。(由 Stefan Tatschner 和 Zackery Spytz 在 bpo-25780 中贡献。)

socket 模块现在支持支持它的平台上的 CAN_J1939 协议。(由 Karl Ding 在 bpo-40291 中贡献。)

socket 模块现在有了 socket.send_fds()socket.recv_fds() 函数。(由 Joannah Nanjekye、Shinya Okano 和 Victor Stinner 在 bpo-28724 中贡献。)

time

在 AIX 上,thread_time() 现在使用具有纳秒分辨率的 thread_cputime() 实现,而不是使用具有 10 毫秒分辨率的 clock_gettime(CLOCK_THREAD_CPUTIME_ID)。(由 Batuhan Taskaya 在 bpo-40192 中贡献)

sys

添加了一个新的 sys.platlibdir 属性:特定于平台的库目录的名称。它用于构建标准库的路径和已安装扩展模块的路径。在大多数平台上它等于 "lib"。在 Fedora 和 SuSE 上,在 64 位平台上它等于 "lib64"。(由 Jan Matějek、Matěj Cepl、Charalampos Stratakis 和 Victor Stinner 在 bpo-1294959 中贡献。)

以前,当非交互时,sys.stderr 是块缓冲的。现在 stderr 默认为始终是行缓冲的。(由 Jendrik Seipp 在 bpo-13601 中贡献。)

tracemalloc

添加了 tracemalloc.reset_peak(),用于将跟踪内存块的峰值大小设置为当前大小,以测量特定代码段的峰值。(由 Huon Wilson 在 bpo-40630 中贡献。)

typing

PEP 593 引入了 typing.Annotated 类型来使用特定于上下文的元数据装饰现有类型,并为 typing.get_type_hints() 添加了新的 include_extras 参数以在运行时访问元数据。(由 Till Varoquaux 和 Konstantin Kashin 贡献。)

unicodedata

Unicode 数据库已更新到 13.0.0 版本。( bpo-39926 )。

venv

venv 提供的激活脚本现在都通过始终使用 __VENV_PROMPT__ 指定的值来一致地指定其提示符自定义。以前,一些脚本无条件地使用 __VENV_PROMPT__,其他脚本仅在它恰好被设置时才使用 (这是默认情况),而一个脚本使用 __VENV_NAME__ 代替。(由 Brett Cannon 在 bpo-37663 中贡献。)

xml

在将 xml.etree.ElementTree 序列化为 XML 文件时,现在会保留属性内的空白字符。EOLN 不再被标准化为 "n"。这是关于如何解释 XML 规范 2.11 节的讨论结果。(由 Mefistotelis 在 bpo-39011 中贡献。)

优化

  • 优化了在推导式中赋值临时变量的惯用方法。现在,推导式中的 for y in [expr] 与简单的赋值 y = expr 一样快。例如

    sums = [s for s in [0] for x in data for s in [s + x]]

    := 运算符不同,这种惯用方法不会将变量泄漏到外部作用域。

    (由 Serhiy Storchaka 在 bpo-32856 中贡献。)

  • 优化了多线程应用程序中的信号处理。如果主线程以外的线程收到信号,则不再在每个字节码指令处中断字节码评估循环以检查无法处理的挂起信号。只有主解释器的主线程才能处理信号。

    以前,字节码评估循环会在每个指令处中断,直到主线程处理信号。(由 Victor Stinner 在 bpo-40010 中贡献。)

  • 使用 closefrom() 优化了 FreeBSD 上的 subprocess 模块。(由 Ed Maste、Conrad Meyer、Kyle Evans、Kubilay Kocak 和 Victor Stinner 在 bpo-38061 中贡献。)

  • 对于适合 long 的值,PyLong_FromDouble() 现在快了 1.87 倍。(由 Sergey Fedoseev 在 bpo-37986 中贡献。)

  • 许多 Python 内置函数 (rangetuplesetfrozensetlistdict) 现在通过使用 PEP 590 向量调用协议来加速。(由 Donghee Na、Mark Shannon、Jeroen Demeyer 和 Petr Viktorin 在 bpo-37207 中贡献。)

  • 优化了当另一个集合比基本集合大得多时 difference_update() 的性能。(由 Evgeny Kapun 建议,代码由 Michele Orrù 在 bpo-8425 中贡献。)

  • Python 的小型对象分配器 (obmalloc.c) 现在允许(不超过)一个空的 arena 保留可用,以便立即重用,而无需将其返回给操作系统。这可以防止在简单的循环中出现抖动,在简单的循环中,arena 可能会在每次迭代时重新创建和销毁。(由 Tim Peters 在 bpo-37257 中贡献。)

  • 浮点数运算的 向下取整除法 现在具有更好的性能。此外,还更新了此运算的 ZeroDivisionError 的消息。(由 Donghee Na 在 bpo-39434 中贡献。)

  • 使用 UTF-8 和 ascii 编解码器解码短 ASCII 字符串现在快了大约 15%。(由 Inada Naoki 在 bpo-37348 中贡献。)

以下是 Python 3.4 到 Python 3.9 的性能改进摘要

Python version                       3.4     3.5     3.6     3.7     3.8    3.9
--------------                       ---     ---     ---     ---     ---    ---

Variable and attribute read access:
    read_local                       7.1     7.1     5.4     5.1     3.9    3.9
    read_nonlocal                    7.1     8.1     5.8     5.4     4.4    4.5
    read_global                     15.5    19.0    14.3    13.6     7.6    7.8
    read_builtin                    21.1    21.6    18.5    19.0     7.5    7.8
    read_classvar_from_class        25.6    26.5    20.7    19.5    18.4   17.9
    read_classvar_from_instance     22.8    23.5    18.8    17.1    16.4   16.9
    read_instancevar                32.4    33.1    28.0    26.3    25.4   25.3
    read_instancevar_slots          27.8    31.3    20.8    20.8    20.2   20.5
    read_namedtuple                 73.8    57.5    45.0    46.8    18.4   18.7
    read_boundmethod                37.6    37.9    29.6    26.9    27.7   41.1

Variable and attribute write access:
    write_local                      8.7     9.3     5.5     5.3     4.3    4.3
    write_nonlocal                  10.5    11.1     5.6     5.5     4.7    4.8
    write_global                    19.7    21.2    18.0    18.0    15.8   16.7
    write_classvar                  92.9    96.0   104.6   102.1    39.2   39.8
    write_instancevar               44.6    45.8    40.0    38.9    35.5   37.4
    write_instancevar_slots         35.6    36.1    27.3    26.6    25.7   25.8

Data structure read access:
    read_list                       24.2    24.5    20.8    20.8    19.0   19.5
    read_deque                      24.7    25.5    20.2    20.6    19.8   20.2
    read_dict                       24.3    25.7    22.3    23.0    21.0   22.4
    read_strdict                    22.6    24.3    19.5    21.2    18.9   21.5

Data structure write access:
    write_list                      27.1    28.5    22.5    21.6    20.0   20.0
    write_deque                     28.7    30.1    22.7    21.8    23.5   21.7
    write_dict                      31.4    33.3    29.3    29.2    24.7   25.4
    write_strdict                   28.4    29.9    27.5    25.2    23.1   24.5

Stack (or queue) operations:
    list_append_pop                 93.4   112.7    75.4    74.2    50.8   50.6
    deque_append_pop                43.5    57.0    49.4    49.2    42.5   44.2
    deque_append_popleft            43.7    57.3    49.7    49.7    42.8   46.4

Timing loop:
    loop_overhead                    0.5     0.6     0.4     0.3     0.3    0.3

这些结果是根据以下位置的变量访问基准测试脚本生成的:Tools/scripts/var_access_benchmark.py。基准测试脚本以纳秒为单位显示时间。基准测试是在 Intel® Core™ i7-4960HQ 处理器 上测量的,该处理器运行的是在 python.org 上找到的 macOS 64 位版本。

已弃用

  • distutils bdist_msi 命令现在已弃用,请改用 bdist_wheel(wheel 包)。(由 Hugo van Kemenade 在 bpo-39586 中贡献。)

  • 目前,math.factorial() 接受具有非负整数值的 float 实例(如 5.0)。对于非整数和负浮点数,它会引发 ValueError。现在它已被弃用。在未来的 Python 版本中,它将为所有浮点数引发 TypeError。(由 Serhiy Storchaka 在 bpo-37315 中贡献。)

  • parsersymbol 模块已弃用,将在未来的 Python 版本中删除。对于大多数用例,用户可以使用抽象语法树 (AST) 生成和编译阶段,使用 ast 模块。

  • 公共 C API 函数 PyParser_SimpleParseStringFlags()PyParser_SimpleParseStringFlagsFilename()PyParser_SimpleParseFileFlags()PyNode_Compile() 已弃用,并将在 Python 3.10 中与旧的解析器一起删除。

  • 在布尔上下文中使用 NotImplemented 已被弃用,因为它几乎完全是错误的富比较器实现的结果。在未来的 Python 版本中,它将被转换为 TypeError。(由 Josh Rosenberg 在 bpo-35712 中贡献。)

  • random 模块目前接受任何可哈希类型作为可能的种子值。不幸的是,某些类型不能保证具有确定的哈希值。在 Python 3.9 之后,该模块将限制其种子为 Noneintfloatstrbytesbytearray

  • 在不指定 *mode* 参数的情况下打开 GzipFile 文件进行写入已被弃用。在未来的 Python 版本中,默认情况下将始终打开用于读取。指定 *mode* 参数以打开它进行写入并消除警告。(由 Serhiy Storchaka 在 bpo-28286 中贡献。)

  • 弃用了 _tkinter.TkappTypesplit() 方法,而推荐使用具有更一致和可预测行为的 splitlist() 方法。(由 Serhiy Storchaka 在 bpo-38371 中贡献。)

  • 显式地将协程对象传递给 asyncio.wait() 已被弃用,将在 3.11 版本中删除。(由 Yury Selivanov 和 Kyle Stanley 在 bpo-34790 中贡献。)

  • binhex4 和 hexbin4 标准现在已被弃用。binhex 模块和以下 binascii 函数现在已被弃用

    • b2a_hqx(), a2b_hqx()

    • rlecode_hqx(), rledecode_hqx()

    (由 Victor Stinner 在 bpo-39353 中贡献。)

  • astsliceIndexExtSlice 被认为是已弃用的,将在未来的 Python 版本中删除。value 本身应该代替 Index(value) 使用。Tuple(slices, Load()) 应该代替 ExtSlice(slices) 使用。(由 Serhiy Storchaka 在 bpo-34822 中贡献。)

  • astSuiteParamAugLoadAugStore 被认为是已弃用的,将在未来的 Python 版本中删除。它们不是由解析器生成的,并且在 Python 3 中不被代码生成器接受。(由 Batuhan Taskaya 在 bpo-39639bpo-39969 中贡献,以及 Serhiy Storchaka 在 bpo-39988 中贡献。)

  • PyEval_InitThreads()PyEval_ThreadsInitialized() 函数现在已被弃用,将在 Python 3.11 中删除。调用 PyEval_InitThreads() 现在没有任何作用。GIL 自 Python 3.7 起由 Py_Initialize() 初始化。(由 Victor Stinner 在 bpo-39877 中贡献。)

  • None 作为第一个参数传递给 shlex.split() 函数已被弃用。(由 Zackery Spytz 在 bpo-33262 中贡献。)

  • smtpd.MailmanProxy() 现在已被弃用,因为它在没有外部模块 mailman 的情况下无法使用。(由 Samuel Colvin 在 bpo-35800 中贡献。)

  • lib2to3 模块现在会发出 PendingDeprecationWarning。Python 3.9 切换到 PEG 解析器(参见 PEP 617),而 Python 3.10 可能包含 lib2to3 的 LL(1) 解析器无法解析的新语言语法。lib2to3 模块可能会在未来的 Python 版本中从标准库中删除。请考虑第三方替代方案,例如 LibCSTparso。(由 Carl Meyer 在 bpo-40360 中贡献。)

  • random.shuffle() 的 *random* 参数已被弃用。(由 Raymond Hettinger 在 bpo-40465 中贡献)

已删除

  • 已删除 unittest.mock.__version__ 中的错误版本。

  • nntplib.NNTP: xpath()xgtitle() 方法已被删除。这些方法自 Python 3.3 起已被弃用。通常,这些扩展不受 NNTP 服务器管理员支持或未启用。对于 xgtitle(),请改用 nntplib.NNTP.descriptions()nntplib.NNTP.description()。(由 Donghee Na 在 bpo-39366 中贡献。)

  • array.array: tostring()fromstring() 方法已被删除。它们是 tobytes()frombytes() 的别名,自 Python 3.2 起已被弃用。(由 Victor Stinner 在 bpo-38916 中贡献。)

  • 未记录的 sys.callstats() 函数已被删除。自 Python 3.7 起,它已被弃用,并且始终返回 None。它需要一个特殊的构建选项 CALL_PROFILE,该选项已在 Python 3.7 中删除。(由 Victor Stinner 在 bpo-37414 中贡献。)

  • 移除了 sys.getcheckinterval()sys.setcheckinterval() 函数。它们自 Python 3.2 起已弃用。请改用 sys.getswitchinterval()sys.setswitchinterval()。(由 Victor Stinner 在 bpo-37392 中贡献。)

  • 移除了 C 函数 PyImport_Cleanup()。它的文档说明是:“清空模块表。仅供内部使用。”(由 Victor Stinner 在 bpo-36710 中贡献。)

  • 移除了 _dummy_threaddummy_threading 模块。这些模块自 Python 3.7 起已弃用,因为它需要线程支持。(由 Victor Stinner 在 bpo-37312 中贡献。)

  • 移除了 aifc.openfp()aifc.open() 的别名)、sunau.openfp()sunau.open() 的别名)和 wave.openfp()wave.open() 的别名)。它们自 Python 3.7 起已弃用。(由 Victor Stinner 在 bpo-37320 中贡献。)

  • 移除了 threading.ThreadisAlive() 方法。它自 Python 3.8 起已弃用。请改用 is_alive()。(由 Donghee Na 在 bpo-37804 中贡献。)

  • 移除了 ElementTreeElement 类中 ElementTree 模块的 getchildren()getiterator() 方法。它们在 Python 3.2 中已弃用。请使用 iter(x)list(x) 代替 x.getchildren(),并使用 x.iter()list(x.iter()) 代替 x.getiterator()。(由 Serhiy Storchaka 在 bpo-36543 中贡献。)

  • 移除了旧的 plistlib API,它自 Python 3.4 起已弃用。请使用 load()loads()dump()dumps() 函数。此外,移除了 *use_builtin_types* 参数,始终使用标准的 bytes 对象。(由 Jon Janzen 在 bpo-36409 中贡献。)

  • 移除了 C 函数 PyGen_NeedsFinalizing。它在 PEP 442 实现后,未在 CPython 中进行文档记录、测试或使用。由 Joannah Nanjekye 提交补丁。(由 Joannah Nanjekye 在 bpo-15088 中贡献)

  • 移除了 base64.encodestring()base64.decodestring(),这两个别名自 Python 3.1 起已弃用:请改用 base64.encodebytes()base64.decodebytes()。(由 Victor Stinner 在 bpo-39351 中贡献。)

  • 移除了 fractions.gcd() 函数,它自 Python 3.5 起已弃用 (bpo-22486):请改用 math.gcd()。(由 Victor Stinner 在 bpo-39350 中贡献。)

  • 移除了 bz2.BZ2File 的 *buffering* 参数。自 Python 3.0 起,它被忽略并且使用它会发出 DeprecationWarning。请传递一个打开的文件对象来控制文件的打开方式。(由 Victor Stinner 在 bpo-39357 中贡献。)

  • 移除了 json.loads() 的 *encoding* 参数。自 Python 3.1 起,它被弃用并被忽略;自 Python 3.8 起,使用它会发出 DeprecationWarning。(由 Inada Naoki 在 bpo-39377 中贡献。)

  • 不再支持 with (await asyncio.lock):with (yield from asyncio.lock): 语句,请改用 async with lock。对于 asyncio.Conditionasyncio.Semaphore 也是如此。(由 Andrew Svetlov 在 bpo-34793 中贡献。)

  • 移除了 sys.getcounts() 函数、-X showalloccount 命令行选项以及 C 结构 PyConfigshow_alloc_count 字段。它们需要通过定义 COUNT_ALLOCS 宏来进行特殊的 Python 构建。(由 Victor Stinner 在 bpo-39489 中贡献。)

  • 移除了 typing.NamedTuple 类的 _field_types 属性。它自 Python 3.8 起已弃用。请改用 __annotations__ 属性。(由 Serhiy Storchaka 在 bpo-40182 中贡献。)

  • 移除了 symtable.SymbolTable.has_exec() 方法。它自 2006 年起已弃用,并且调用时仅返回 False。(由 Batuhan Taskaya 在 bpo-40208 中贡献。)

  • 移除了 asyncio.Task.current_task()asyncio.Task.all_tasks()。它们自 Python 3.7 起已弃用,您可以改用 asyncio.current_task()asyncio.all_tasks()。(由 Rémi Lapeyre 在 bpo-40967 中贡献。)

  • 移除了 html.parser.HTMLParser 类中的 unescape() 方法(它自 Python 3.4 起已弃用)。应该使用 html.unescape() 将字符引用转换为相应的 Unicode 字符。

移植到 Python 3.9

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

Python API 中的更改

  • __import__()importlib.util.resolve_name() 现在会抛出 ImportError 异常,而之前会抛出 ValueError 异常。捕获特定异常类型并支持 Python 3.9 及更早版本的调用者需要使用 except (ImportError, ValueError): 来捕获两种异常。

  • venv 激活脚本在 __VENV_PROMPT__ 设置为 "" 时不再特殊处理。

  • select.epoll.unregister() 方法不再忽略 EBADF 错误。(由 Victor Stinner 在 bpo-39239 中贡献。)

  • bz2.BZ2File 的 *compresslevel* 参数现在是仅限关键字的,因为 *buffering* 参数已被删除。(由 Victor Stinner 在 bpo-39357 中贡献。)

  • 简化的下标 AST。简单索引将由它们的值表示,扩展切片将表示为元组。Index(value) 将返回 value 本身,ExtSlice(slices) 将返回 Tuple(slices, Load())。(由 Serhiy Storchaka 在 bpo-34822 中贡献。)

  • 当使用 -E-I 命令行选项时,importlib 模块现在会忽略 PYTHONCASEOK 环境变量。

  • encoding 参数已作为仅限关键字的参数添加到 ftplib.FTPftplib.FTP_TLS 类中,并且默认编码已从 Latin-1 更改为 UTF-8,以遵循 RFC 2640

  • asyncio.loop.shutdown_default_executor() 已添加到 AbstractEventLoop,这意味着继承自它的替代事件循环应定义此方法。(由 Kyle Stanley 在 bpo-34037 中贡献。)

  • __future__ 模块中未来标志的常量值已更新,以防止与编译器标志冲突。之前,PyCF_ALLOW_TOP_LEVEL_AWAITCO_FUTURE_DIVISION 冲突。(由 Batuhan Taskaya 在 bpo-39562 中贡献。)

  • array('u') 现在使用 wchar_t 作为 C 类型,而不是 Py_UNICODE。此更改不影响其行为,因为自 Python 3.3 以来,Py_UNICODEwchar_t 的别名。(由 Inada Naoki 在 bpo-34538 中贡献。)

  • 当传递名称 'root' 时,logging.getLogger() API 现在返回根记录器,而之前它返回一个名为 'root' 的非根记录器。这可能会影响用户代码显式需要一个名为 'root' 的非根记录器的情况,或者在一些名为 'root.py' 的顶层模块中使用 logging.getLogger(__name__) 实例化记录器的情况。(由 Vinay Sajip 在 bpo-37742 中贡献。)

  • 当传递的不是 strPurePath 的实例时,PurePath 的除法处理现在返回 NotImplemented,而不是抛出 TypeError。这允许创建不继承自上述类型的兼容类。(由 Roger Aiudi 在 bpo-34775 中贡献。)

  • 从 Python 3.9.5 开始,ipaddress 模块不再接受 IPv4 地址字符串中的任何前导零。前导零是模棱两可的,并且被某些库解释为八进制表示法。例如,遗留函数 socket.inet_aton() 将前导零视为八进制表示法。现代 inet_pton() 的 glibc 实现不接受任何前导零。(由 Christian Heimes 在 bpo-36384 中贡献。)

  • codecs.lookup() 现在以与 encodings.normalize_encoding() 相同的方式规范化编码名称,不同之处在于 codecs.lookup() 还会将名称转换为小写。例如,"latex+latin1" 编码名称现在被规范化为 "latex_latin1"。(由 Jordon Xu 在 bpo-37751 中贡献。)

C API 中的更改

  • 堆分配类型的实例(例如使用 PyType_FromSpec() 和类似的 API 创建的实例)自 Python 3.8 起就持有对其类型对象的引用。正如 Python 3.8 的“C API 中的更改”中所述,对于绝大多数情况,应该没有副作用,但对于具有自定义 tp_traverse 函数的类型,请确保堆分配类型的所有自定义 tp_traverse 函数都访问该对象的类型。

    示例

    int
    foo_traverse(foo_struct *self, visitproc visit, void *arg) {
    // Rest of the traverse function
    #if PY_VERSION_HEX >= 0x03090000
        // This was not needed before Python 3.9 (Python issue 35810 and 40217)
        Py_VISIT(Py_TYPE(self));
    #endif
    }
    

    如果你的 traverse 函数委托给其基类(或其他类型)的 tp_traverse,请确保 Py_TYPE(self) 只被访问一次。请注意,只有 堆类型 才需要在 tp_traverse 中访问该类型。

    例如,如果你的 tp_traverse 函数包含

    base->tp_traverse(self, visit, arg)
    

    那么添加

    #if PY_VERSION_HEX >= 0x03090000
        // This was not needed before Python 3.9 (bpo-35810 and bpo-40217)
        if (base->tp_flags & Py_TPFLAGS_HEAPTYPE) {
            // a heap type's tp_traverse already visited Py_TYPE(self)
        } else {
            Py_VISIT(Py_TYPE(self));
        }
    #else
    

    (有关更多信息,请参阅 bpo-35810bpo-40217。)

  • 函数 PyEval_CallObjectPyEval_CallFunctionPyEval_CallMethodPyEval_CallObjectWithKeywords 已被弃用。请改用 PyObject_Call() 及其变体。(有关更多详细信息,请参阅 bpo-29548。)

CPython 字节码更改

  • 添加了 LOAD_ASSERTION_ERROR 操作码来处理 assert 语句。以前,如果 AssertionError 异常被覆盖,则 assert 语句将无法正常工作。(由 Zackery Spytz 在 bpo-34880 中贡献。)

  • COMPARE_OP 操作码被拆分为四个不同的指令

    • COMPARE_OP 用于丰富比较

    • IS_OP 用于 'is' 和 'is not' 测试

    • CONTAINS_OP 用于 ‘in’ 和 ‘not in’ 测试。

    • JUMP_IF_NOT_EXC_MATCH 用于检查 ‘try-except’ 语句中的异常。

    (由 Mark Shannon 在 bpo-39156 中贡献。)

构建变更

  • configure 脚本添加了 --with-platlibdir 选项:平台特定库目录的名称,存储在新属性 sys.platlibdir 中。有关更多信息,请参见 sys.platlibdir 属性。(由 Jan Matějek、Matěj Cepl、Charalampos Stratakis 和 Victor Stinner 在 bpo-1294959 中贡献。)

  • 已删除 COUNT_ALLOCS 特殊构建宏。(由 Victor Stinner 在 bpo-39489 中贡献。)

  • 在非 Windows 平台上,现在需要 setenv()unsetenv() 函数来构建 Python。(由 Victor Stinner 在 bpo-39395 中贡献。)

  • 在非 Windows 平台上,现在官方不支持创建 bdist_wininst 安装程序。(有关更多详细信息,请参见 bpo-10945。)

  • 从源代码在 macOS 上构建 Python 时,如果非系统 Tcl 和 Tk 框架安装在 /Library/Frameworks 中,则 _tkinter 现在会链接它们,就像在较旧版本的 macOS 上一样。如果通过使用 --enable-universalsdk-isysroot 显式配置了 macOS SDK,则仅搜索 SDK 本身。仍然可以使用 --with-tcltk-includes--with-tcltk-libs 覆盖默认行为。(由 Ned Deily 在 bpo-34956 中贡献。)

  • 现在可以为 Windows 10 ARM64 构建 Python。(由 Steve Dower 在 bpo-33125 中贡献。)

  • 当使用 --pgo 时,现在会跳过一些单独的测试。有问题的测试显著增加了 PGO 任务时间,并且可能无助于改进最终可执行文件的优化。这使任务速度提高了约 15 倍。运行完整的单元测试套件很慢。此更改可能会导致优化的构建略差,因为将执行的代码分支较少。如果您愿意等待较慢的构建,则可以使用 ./configure [..] PROFILE_TASK="-m test --pgo-extended" 恢复旧的行为。我们不保证哪个 PGO 任务集会产生更快的构建。关心此问题的用户应运行自己的相关基准测试,因为结果可能取决于环境、工作负载和编译器工具链。(有关更多详细信息,请参见 bpo-36044bpo-37707。)

C API 变更

新功能

移植到 Python 3.9

  • PyInterpreterState.eval_frame (PEP 523) 现在需要一个新的强制性 tstate 参数 (PyThreadState*)。(由 Victor Stinner 在 bpo-38500 中贡献。)

  • 扩展模块:如果请求了模块状态但尚未分配模块状态,则不再调用 m_traversem_clearm_free 函数。这种情况发生在模块创建之后且执行模块之前(Py_mod_exec 函数)。更准确地说,如果 m_size 大于 0 且模块状态(由 PyModule_GetState() 返回)为 NULL,则不会调用这些函数。

    没有模块状态的扩展模块(m_size <= 0)不受影响。

  • 如果在子解释器中调用 Py_AddPendingCall(),则该函数现在计划从子解释器中调用,而不是从主解释器中调用。每个子解释器现在都有自己的计划调用列表。(由 Victor Stinner 在 bpo-39984 中贡献。)

  • 当使用 -E 选项(如果 PyConfig.use_environment 设置为 0)时,不再使用 Windows 注册表来初始化 sys.path。在 Windows 上嵌入 Python 时,这一点很重要。(由 Zackery Spytz 在 bpo-8901 中贡献。)

  • 全局变量 PyStructSequence_UnnamedField 现在是一个常量,并引用一个常量字符串。(由 Serhiy Storchaka 在 bpo-38650 中贡献。)

  • PyGC_Head 结构现在是不透明的。它仅在内部 C API (pycore_gc.h) 中定义。(由 Victor Stinner 在 bpo-40241 中贡献。)

  • Py_UNICODE_COPYPy_UNICODE_FILLPyUnicode_WSTR_LENGTHPyUnicode_FromUnicode()PyUnicode_AsUnicode()_PyUnicode_AsUnicodePyUnicode_AsUnicodeAndSize() 在 C 中被标记为已弃用。自 Python 3.3 以来,它们已被 PEP 393 弃用。(由 Inada Naoki 在 bpo-36346 中贡献。)

  • Py_FatalError() 函数被一个宏替换,该宏会自动记录当前函数的名称,除非定义了 Py_LIMITED_API 宏。(由 Victor Stinner 在 bpo-39882 中贡献。)

  • vectorcall 协议现在要求调用者仅传递字符串作为关键字名称。(有关详细信息,请参阅 bpo-37540。)

  • 许多宏和函数的实现细节现在被隐藏

    (有关更多详细信息,请参阅 bpo-40170。)

已移除

  • 从受限 C API 中排除了 pyfpe.hPyFPE_START_PROTECT()PyFPE_END_PROTECT() 宏。(由 Victor Stinner 在 bpo-38835 中贡献。)

  • PyTypeObjecttp_print 插槽已被删除。它用于在 Python 2.7 及更早版本中将对象打印到文件。自 Python 3.0 以来,它已被忽略且未使用。(由 Jeroen Demeyer 在 bpo-36974 中贡献。)

  • 有限 C API 中的更改(如果定义了 Py_LIMITED_API 宏)

    • 从受限 C API 中排除了以下函数

      • PyThreadState_DeleteCurrent() (由 Joannah Nanjekye 在 bpo-37878 中贡献。)

      • _Py_CheckRecursionLimit

      • _Py_NewReference()

      • _Py_ForgetReference()

      • _PyTraceMalloc_NewReference()

      • _Py_GetRefTotal()

      • 垃圾箱机制在受限 C API 中从未起作用。

      • PyTrash_UNWIND_LEVEL

      • Py_TRASHCAN_BEGIN_CONDITION

      • Py_TRASHCAN_BEGIN

      • Py_TRASHCAN_END

      • Py_TRASHCAN_SAFE_BEGIN

      • Py_TRASHCAN_SAFE_END

    • 将以下函数和定义移动到内部 C API

      • _PyDebug_PrintTotalRefs()

      • _Py_PrintReferences()

      • _Py_PrintReferenceAddresses()

      • _Py_tracemalloc_config

      • _Py_AddToAllObjects() (特定于 Py_TRACE_REFS 构建)

    (由 Victor Stinner 在 bpo-38644bpo-39542 中贡献。)

  • 删除了 _PyRuntime.getframe 钩子,并删除了 _PyThreadState_GetFrame 宏,该宏是 _PyRuntime.getframe 的别名。它们仅由内部 C API 公开。还删除了 PyThreadFrameGetter 类型。(由 Victor Stinner 在 bpo-39946 中贡献。)

  • 从 C API 中删除了以下函数。显式调用 PyGC_Collect() 以清除所有空闲列表。(由 Inada Naoki 和 Victor Stinner 在 bpo-37340bpo-38896bpo-40428 中贡献。)

    • PyAsyncGen_ClearFreeLists()

    • PyContext_ClearFreeList()

    • PyDict_ClearFreeList()

    • PyFloat_ClearFreeList()

    • PyFrame_ClearFreeList()

    • PyList_ClearFreeList()

    • PyMethod_ClearFreeList()PyCFunction_ClearFreeList():已删除绑定方法对象的空闲列表。

    • PySet_ClearFreeList():集合空闲列表已在 Python 3.4 中删除。

    • PyTuple_ClearFreeList()

    • PyUnicode_ClearFreeList():Unicode 空闲列表已在 Python 3.3 中删除。

  • 删除了 _PyUnicode_ClearStaticStrings() 函数。(由 Victor Stinner 在 bpo-39465 中贡献。)

  • 删除了 Py_UNICODE_MATCH。它已被 PEP 393 弃用,并且自 Python 3.3 以来已损坏。可以使用 PyUnicode_Tailmatch() 函数代替。(由 Inada Naoki 在 bpo-36346 中贡献。)

  • 清理了已定义但没有实现的接口的头文件。要删除的公共 API 符号为:_PyBytes_InsertThousandsGroupingLocale_PyBytes_InsertThousandsGrouping_Py_InitializeFromArgs_Py_InitializeFromWideArgs_PyFloat_Repr_PyFloat_Digits_PyFloat_DigitsInitPyFrame_ExtendStack_PyAIterWrapper_TypePyNullImporter_TypePyCmpWrapper_TypePySortWrapper_TypePyNoArgsFunction。(由 Pablo Galindo Salgado 在 bpo-39372 中贡献。)

Python 3.9.1 中的重要更改

typing

typing.Literal 的行为已更改为符合 PEP 586,并匹配 PEP 中指定的静态类型检查器的行为。

  1. Literal 现在会删除重复的参数。

  2. Literal 对象之间的相等比较现在与顺序无关。

  3. Literal 比较现在会考虑类型。例如,Literal[0] == Literal[False] 之前会被评估为 True。现在它为 False。为了支持此更改,内部使用的类型缓存现在支持区分类型。

  4. 如果 Literal 对象的任何参数不是 可哈希的,则在进行相等性比较时,Literal 对象现在会引发 TypeError 异常。请注意,使用可变参数声明 Literal 不会引发错误。

    >>> from typing import Literal
    >>> Literal[{0}]
    >>> Literal[{0}] == Literal[{False}]
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    TypeError: unhashable type: 'set'
    

(由 Yurii Karabas 在 bpo-42345 中贡献。)

macOS 11.0 (Big Sur) 和 Apple Silicon Mac 支持

从 3.9.1 开始,Python 现在完全支持在 macOS 11.0 (Big Sur) 和基于 ARM64 架构的 Apple Silicon Mac 上构建和运行。新的通用构建变体 universal2 现在可用于在同一组可执行文件中原生支持 ARM64Intel 64。现在还可以在当前版本的 macOS 上构建二进制文件,以部署在各种较旧的 macOS 版本(已测试到 10.9)上,同时根据运行时使用的操作系统版本有条件地提供一些较新的操作系统功能和选项(“弱链接”)。

(由 Ronald Oussoren 和 Lawrence D’Anna 在 bpo-41100 中贡献。)

Python 3.9.2 中的显著变化

collections.abc

collections.abc.Callable 泛型现在会展平类型参数,类似于 typing.Callable 当前所做的。这意味着 collections.abc.Callable[[int, str], str]__args__ 将为 (int, str, str);之前是 ([int, str], str)。为了允许此更改,现在可以对 types.GenericAlias 进行子类化,并且在对 collections.abc.Callable 类型进行下标时,将返回一个子类。通过 typing.get_args()__args__ 访问参数的代码需要考虑此更改。对于可能在 Python 3.9.1 中静默通过的 collections.abc.Callable 的无效参数化形式,可能会发出 DeprecationWarning。此 DeprecationWarning 将在 Python 3.10 中变为 TypeError。(由 Ken Jin 在 bpo-42195 中贡献。)

urllib.parse

早期版本的 Python 允许在 urllib.parse.parse_qs()urllib.parse.parse_qsl() 中同时使用 ;& 作为查询参数分隔符。由于安全问题,并为了符合较新的 W3C 建议,此更改为仅允许单个分隔符键,默认使用 &。此更改还会影响 cgi.parse()cgi.parse_multipart(),因为它们在内部使用受影响的函数。有关更多详细信息,请参阅它们各自的文档。(由 Adam Goldschmidt、Senthil Kumaran 和 Ken Jin 在 bpo-42967 中贡献。)

Python 3.9.3 中的显著变化

一个安全修复更改了 ftplib.FTP 的行为,以在设置被动数据通道时不信任从远程服务器发送的 IPv4 地址。我们改为重用 ftp 服务器 IP 地址。对于需要旧行为的非常规代码,请将 FTP 实例上的 trust_server_pasv_ipv4_address 属性设置为 True。(请参阅 gh-87451

Python 3.9.5 中的显著变化

urllib.parse

URL 的某些部分中存在换行符或制表符允许进行某些形式的攻击。根据更新了 RFC 3986 的 WHATWG 规范,urllib.parse 中的解析器会从 URL 中删除 ASCII 换行符 \n\r 和制表符 \t 字符,从而防止此类攻击。删除的字符由新的模块级变量 urllib.parse._UNSAFE_URL_BYTES_TO_REMOVE 控制。(请参阅 gh-88048

3.9.14 中的显著安全特性

在 2(二进制)、4、8(八进制)、16(十六进制)或 32 之外的基数(例如基数 10(十进制))中,intstr 之间的转换,如果字符串形式的位数超过限制,现在会引发 ValueError,以避免由于算法复杂性而导致潜在的拒绝服务攻击。这是针对 CVE 2020-10735 的缓解措施。此限制可以通过环境变量、命令行标志或 sys API 进行配置或禁用。请参阅 整数字符串转换长度限制 文档。字符串形式的默认限制为 4300 位。

3.9.17 中的显著变化

tarfile

  • tarfile 中的提取方法和 shutil.unpack_archive() 具有一个新的 filter 参数,允许限制可能令人惊讶或危险的 tar 功能,例如在目标目录之外创建文件。有关详细信息,请参阅 提取过滤器。在 Python 3.12 中,不使用 filter 参数将显示 DeprecationWarning。在 Python 3.14 中,默认值将切换为 'data'。(由 Petr Viktorin 在 PEP 706 中贡献。)