Python 3.9 新特性¶
- 编辑:
Łukasz Langa
本文介绍了 Python 3.9 相对于 3.8 的新特性。 Python 3.9 于 2020 年 10 月 5 日发布。有关完整详细信息,请参阅更新日志。
参见
PEP 596 - Python 3.9 发布计划
摘要 – 版本亮点¶
新的语法特性
新的内置特性
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 模块(
_abc
、audioop
、_bz2
、_codecs
、_contextvars
、_crypt
、_functools
、_json
、_locale
、math
、operator
、resource
、time
、_weakref
) 现在使用 PEP 489 定义的多阶段初始化;许多标准库模块 (
audioop
、ast
、grp
、_hashlib
、pwd
、_posixsubprocess
、random
、select
、struct
、termios
、zlib
) 现在使用 PEP 384 定义的稳定 ABI。
新的库模块
发布过程变更
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
命令行选项测试你的应用程序,查看 DeprecationWarning
和 PendingDeprecationWarning
,或者甚至使用 -W
error
将它们视为错误。 警告过滤器 可以用来忽略来自第三方代码的警告。
Python 3.9 是提供这些 Python 2 向后兼容层的最后一个版本,为的是给 Python 项目维护者更多时间来组织移除 Python 2 的支持,并添加对 Python 3.9 的支持。
为了向后兼容,在 collections
模块中,抽象基类 的别名,例如 collections.Mapping
是 collections.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'}
删除前缀和后缀的新字符串方法¶
添加了 str.removeprefix(prefix)
和 str.removesuffix(suffix)
,以便轻松地从字符串中删除不需要的前缀或后缀。还添加了相应的 bytes
、bytearray
和 collections.UserString
方法。 有关完整说明,请参阅 PEP 616。(由 Dennis Sweeney 在 bpo-39939 中贡献。)
标准集合中的类型提示泛型¶
在类型注解中,你现在可以使用内置集合类型(如 list
和 dict
)作为泛型类型,而不是从 typing
导入相应的大写类型(例如 List
或 Dict
)。 标准库中的一些其他类型现在也是泛型的,例如 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)
一致。 对于bytes
和bytearray
对象也有类似的更改。(由 Serhiy Storchaka 在 bpo-28029 中贡献。)现在任何有效表达式都可以用作装饰器。 以前,语法限制要大得多。 有关详细信息,请参阅 PEP 614。(由 Brandt Bucher 在 bpo-39702 中贡献。)
改进了
typing
模块的帮助。 现在会显示所有特殊形式和特殊泛型别名(例如Union
和List
)的文档字符串。 将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-41848 和 bpo-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 中贡献。)
从 ThreadPoolExecutor
和 ProcessPoolExecutor
中移除了守护线程。这提高了与子解释器的兼容性,并提高了它们关闭过程的可预测性。(由 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_GETLK
、F_OFD_SETLK
和 F_OFD_SETLKW
。(由 Donghee Na 在 bpo-38602 中贡献。)
ftplib¶
如果为构造函数提供的超时时间为零,FTP
和 FTP_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_HINTS
、418 IM_A_TEAPOT
和 425 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¶
IMAP4
和 IMAP4_SSL
现在在其构造函数中有一个可选的 timeout 参数。此外,open()
方法现在也进行了此更改,带有一个可选的 timeout 参数。IMAP4_SSL
和 IMAP4_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.arguments
从 OrderedDict
更改为常规字典。(由 Inada Naoki 在 bpo-36350 和 bpo-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-39479 和 bpo-39648 中贡献。)
添加了 math.nextafter()
:返回 x 之后朝向 y 的下一个浮点数值。(由 Victor Stinner 在 bpo-39288 中贡献。)
添加了 math.ulp()
:返回浮点数的最小有效位的值。(由 Victor Stinner 在 bpo-39310 中贡献。)
multiprocessing¶
multiprocessing.SimpleQueue
类有一个新的 close()
方法来显式关闭队列。(由 Victor Stinner 在 bpo-30966 中贡献。)
nntplib¶
NNTP
和 NNTP_SSL
现在如果构造函数的给定超时时间为零,则会引发 ValueError
,以防止创建非阻塞套接字。(由 Donghee Na 在 bpo-39259 中贡献。)
os¶
为 si_code
添加了 CLD_KILLED
和 CLD_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¶
POP3
和 POP3_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¶
SMTP
和 SMTP_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 内置函数 (
range
、tuple
、set
、frozenset
、list
、dict
) 现在通过使用 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 中贡献。)parser
和symbol
模块已弃用,将在未来的 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 之后,该模块将限制其种子为None
、int
、float
、str
、bytes
和bytearray
。在不指定 *mode* 参数的情况下打开
GzipFile
文件进行写入已被弃用。在未来的 Python 版本中,默认情况下将始终打开用于读取。指定 *mode* 参数以打开它进行写入并消除警告。(由 Serhiy Storchaka 在 bpo-28286 中贡献。)弃用了
_tkinter.TkappType
的split()
方法,而推荐使用具有更一致和可预测行为的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 中贡献。)
ast
类slice
、Index
和ExtSlice
被认为是已弃用的,将在未来的 Python 版本中删除。value
本身应该代替Index(value)
使用。Tuple(slices, Load())
应该代替ExtSlice(slices)
使用。(由 Serhiy Storchaka 在 bpo-34822 中贡献。)ast
类Suite
、Param
、AugLoad
和AugStore
被认为是已弃用的,将在未来的 Python 版本中删除。它们不是由解析器生成的,并且在 Python 3 中不被代码生成器接受。(由 Batuhan Taskaya 在 bpo-39639 和 bpo-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 版本中从标准库中删除。请考虑第三方替代方案,例如 LibCST 或 parso。(由 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_thread
和dummy_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.Thread
的isAlive()
方法。它自 Python 3.8 起已弃用。请改用is_alive()
。(由 Donghee Na 在 bpo-37804 中贡献。)移除了
ElementTree
和Element
类中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.Condition
和asyncio.Semaphore
也是如此。(由 Andrew Svetlov 在 bpo-34793 中贡献。)移除了
sys.getcounts()
函数、-X showalloccount
命令行选项以及 C 结构PyConfig
的show_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.FTP
和ftplib.FTP_TLS
类中,并且默认编码已从 Latin-1 更改为 UTF-8,以遵循 RFC 2640。asyncio.loop.shutdown_default_executor()
已添加到AbstractEventLoop
,这意味着继承自它的替代事件循环应定义此方法。(由 Kyle Stanley 在 bpo-34037 中贡献。)__future__
模块中未来标志的常量值已更新,以防止与编译器标志冲突。之前,PyCF_ALLOW_TOP_LEVEL_AWAIT
与CO_FUTURE_DIVISION
冲突。(由 Batuhan Taskaya 在 bpo-39562 中贡献。)array('u')
现在使用wchar_t
作为 C 类型,而不是Py_UNICODE
。此更改不影响其行为,因为自 Python 3.3 以来,Py_UNICODE
是wchar_t
的别名。(由 Inada Naoki 在 bpo-34538 中贡献。)当传递名称
'root'
时,logging.getLogger()
API 现在返回根记录器,而之前它返回一个名为'root'
的非根记录器。这可能会影响用户代码显式需要一个名为'root'
的非根记录器的情况,或者在一些名为'root.py'
的顶层模块中使用logging.getLogger(__name__)
实例化记录器的情况。(由 Vinay Sajip 在 bpo-37742 中贡献。)当传递的不是
str
或PurePath
的实例时,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
函数
PyEval_CallObject
、PyEval_CallFunction
、PyEval_CallMethod
和PyEval_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-36044 和 bpo-37707。)
C API 变更¶
新功能¶
PEP 573:添加了
PyType_FromModuleAndSpec()
以将模块与类关联;PyType_GetModule()
和PyType_GetModuleState()
来检索模块及其状态;以及PyCMethod
和METH_METHOD
允许方法访问其定义所在的类。(由 Marcel Plch 和 Petr Viktorin 在 bpo-38787 中贡献。)添加了
PyFrame_GetCode()
函数:获取帧代码。添加了PyFrame_GetBack()
函数:获取帧的下一个外部帧。(由 Victor Stinner 在 bpo-40421 中贡献。)将
PyFrame_GetLineNumber()
添加到有限的 C API。(由 Victor Stinner 在 bpo-40421 中贡献。)添加了
PyThreadState_GetInterpreter()
和PyInterpreterState_Get()
函数来获取解释器。添加了PyThreadState_GetFrame()
函数来获取 Python 线程状态的当前帧。添加了PyThreadState_GetID()
函数:获取 Python 线程状态的唯一标识符。(由 Victor Stinner 在 bpo-39947 中贡献。)向 C API 添加了一个新的公共
PyObject_CallNoArgs()
函数,该函数调用没有参数的可调用 Python 对象。这是调用没有参数的可调用 Python 对象的最有效方法。(由 Victor Stinner 在 bpo-37194 中贡献。)有限 C API 中的更改(如果定义了
Py_LIMITED_API
宏)为有限的 API 提供
Py_EnterRecursiveCall()
和Py_LeaveRecursiveCall()
作为常规函数。以前,它们被定义为宏,但是这些宏无法与有限的 C API 编译,因为有限的 C API 无法访问PyThreadState.recursion_depth
字段(该结构在有限的 C API 中是不透明的)。PyObject_INIT()
和PyObject_INIT_VAR()
变为常规的“不透明”函数,以隐藏实现细节。
添加了
PyModule_AddType()
函数以帮助向模块添加类型。(由 Donghee Na 在 bpo-40024 中贡献。)向公共 API 添加了函数
PyObject_GC_IsTracked()
和PyObject_GC_IsFinalized()
,以允许查询 Python 对象当前是否正在被垃圾收集器跟踪或是否已由垃圾收集器最终确定。(由 Pablo Galindo Salgado 在 bpo-40241 中贡献。)添加了
_PyObject_FunctionStr()
以获取类似函数的对象的用户友好的字符串表示形式。(Jeroen Demeyer 在 bpo-37645 中的补丁。)添加了
PyObject_CallOneArg()
以使用一个位置参数调用对象(Jeroen Demeyer 在 bpo-37483 中的补丁。)
移植到 Python 3.9¶
PyInterpreterState.eval_frame
(PEP 523) 现在需要一个新的强制性 tstate 参数 (PyThreadState*
)。(由 Victor Stinner 在 bpo-38500 中贡献。)扩展模块:如果请求了模块状态但尚未分配模块状态,则不再调用
m_traverse
、m_clear
和m_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_COPY
、Py_UNICODE_FILL
、PyUnicode_WSTR_LENGTH
、PyUnicode_FromUnicode()
、PyUnicode_AsUnicode()
、_PyUnicode_AsUnicode
和PyUnicode_AsUnicodeAndSize()
在 C 中被标记为已弃用。自 Python 3.3 以来,它们已被 PEP 393 弃用。(由 Inada Naoki 在 bpo-36346 中贡献。)Py_FatalError()
函数被一个宏替换,该宏会自动记录当前函数的名称,除非定义了Py_LIMITED_API
宏。(由 Victor Stinner 在 bpo-39882 中贡献。)vectorcall 协议现在要求调用者仅传递字符串作为关键字名称。(有关详细信息,请参阅 bpo-37540。)
许多宏和函数的实现细节现在被隐藏
PyObject_IS_GC()
宏已转换为函数。PyObject_NEW()
宏成为PyObject_New
宏的别名,PyObject_NEW_VAR()
宏成为PyObject_NewVar
宏的别名。它们不再直接访问PyTypeObject.tp_basicsize
成员。PyObject_GET_WEAKREFS_LISTPTR()
宏已转换为函数:该宏直接访问PyTypeObject.tp_weaklistoffset
成员。PyObject_CheckBuffer()
宏已转换为函数:该宏直接访问PyTypeObject.tp_as_buffer
成员。PyIndex_Check()
现在始终声明为一个不透明函数,以隐藏实现细节:删除了PyIndex_Check()
宏。该宏直接访问PyTypeObject.tp_as_number
成员。
(有关更多详细信息,请参阅 bpo-40170。)
已移除¶
从受限 C API 中排除了
pyfpe.h
的PyFPE_START_PROTECT()
和PyFPE_END_PROTECT()
宏。(由 Victor Stinner 在 bpo-38835 中贡献。)PyTypeObject 的
tp_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
构建)
删除了
_PyRuntime.getframe
钩子,并删除了_PyThreadState_GetFrame
宏,该宏是_PyRuntime.getframe
的别名。它们仅由内部 C API 公开。还删除了PyThreadFrameGetter
类型。(由 Victor Stinner 在 bpo-39946 中贡献。)从 C API 中删除了以下函数。显式调用
PyGC_Collect()
以清除所有空闲列表。(由 Inada Naoki 和 Victor Stinner 在 bpo-37340、bpo-38896 和 bpo-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_DigitsInit
、PyFrame_ExtendStack
、_PyAIterWrapper_Type
、PyNullImporter_Type
、PyCmpWrapper_Type
、PySortWrapper_Type
、PyNoArgsFunction
。(由 Pablo Galindo Salgado 在 bpo-39372 中贡献。)
Python 3.9.1 中的重要更改¶
typing¶
typing.Literal
的行为已更改为符合 PEP 586,并匹配 PEP 中指定的静态类型检查器的行为。
Literal
现在会删除重复的参数。Literal
对象之间的相等比较现在与顺序无关。Literal
比较现在会考虑类型。例如,Literal[0] == Literal[False]
之前会被评估为True
。现在它为False
。为了支持此更改,内部使用的类型缓存现在支持区分类型。如果
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
现在可用于在同一组可执行文件中原生支持 ARM64
和 Intel 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(十进制))中,int
和 str
之间的转换,如果字符串形式的位数超过限制,现在会引发 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 中贡献。)