Python 3.12 有什么新变化¶
- 编者
TBD
本文介绍了 Python 3.12 相比 3.11 的新增特性。
更详细的信息可参阅 更新日志。
备注
预发布版用户应当了解到此文档目前处于草稿状态。 它将随着 Python 3.12 的发布进行不断更新,因此即使已经阅读过较早的版本也仍然值得再次查看。
摘要 -- 发布重点¶
新的语法特性:
解释器的改进:
新的类型标注特性:
重要的弃用、移除或限制:
PEP 623: 从 Unicode 中移除 wstr
PEP 632: 移除
distutils
包。 请参阅 the migration guide 了解其替代品的建议。
改进的错误消息¶
Modules from the standard library are now potentially suggested as part of the error messages displayed by the interpreter when a
NameError
is raised to the top level. (Contributed by Pablo Galindo in gh-98254.)>>> sys.version_info Traceback (most recent call last): File "<stdin>", line 1, in <module> NameError: name 'sys' is not defined. Did you forget to import 'sys'?
Improve the error suggestion for
NameError
exceptions for instances. Now if aNameError
is raised in a method and the instance has an attribute that's exactly equal to the name in the exception, the suggestion will includeself.<NAME>
instead of the closest match in the method scope. (Contributed by Pablo Galindo in gh-99139.)>>> class A: ... def __init__(self): ... self.blech = 1 ... ... def foo(self): ... somethin = blech ... >>> A().foo() File "<stdin>", line 1 somethin = blech ^^^^^ NameError: name 'blech' is not defined. Did you mean: 'self.blech'?
Improve the
SyntaxError
error message when the user typesimport x from y
instead offrom y import x
. (Contributed by Pablo Galindo in gh-98931.)>>> import a.y.z from b.y.z File "<stdin>", line 1 import a.y.z from b.y.z ^^^^^^^^^^^^^^^^^^^^^^^ SyntaxError: Did you mean to use 'from ... import ...' instead?
ImportError
exceptions raised from failedfrom <module> import <name>
statements now include suggestions for the value of<name>
based on the available names in<module>
. (Contributed by Pablo Galindo in gh-91058.)>>> from collections import chainmap Traceback (most recent call last): File "<stdin>", line 1, in <module> ImportError: cannot import name 'chainmap' from 'collections'. Did you mean: 'ChainMap'?
新的特性¶
PEP 701:f-字符串的句法形式化¶
PEP 701 lifts some restrictions on the usage of f-strings. Expression components inside f-strings can now be any valid Python expression, including strings reusing the same quote as the containing f-string, multi-line expressions, comments, backslashes, and unicode escape sequences. Let's cover these in detail:
Quote reuse: in Python 3.11, reusing the same quotes as the enclosing f-string raises a
SyntaxError
, forcing the user to either use other available quotes (like using double quotes or triple quotes if the f-string uses single quotes). In Python 3.12, you can now do things like this:>>> songs = ['Take me back to Eden', 'Alkaline', 'Ascensionism'] >>> f"This is the playlist: {", ".join(songs)}" 'This is the playlist: Take me back to Eden, Alkaline, Ascensionism'
请注意,在这一更改之前,对f-字符串的嵌套方式没有明确的限制,但字符串引号不能在f-字符串的表达式组件中重复使用,这使得不可能任意嵌套f-字符串。事实上,这是可以编写的嵌套最多的f-字符串:
>>> f"""{f'''{f'{f"{1+1}"}'}'''}""" '2'
由于现在f-字符串可以在表达式组件中包含任何有效的Python表达式,因此现在可以任意嵌套f-字符串:
>>> f"{f"{f"{f"{f"{f"{1+1}"}"}"}"}"}" '2'
Multi-line expressions and comments: In Python 3.11, f-string expressions must be defined in a single line, even if the expression within the f-string could normally span multiple lines (like literal lists being defined over multiple lines), making them harder to read. In Python 3.12 you can now define f-strings spanning multiple lines, and add inline comments:
>>> f"This is the playlist: {", ".join([ ... 'Take me back to Eden', # My, my, those eyes like fire ... 'Alkaline', # Not acid nor alkaline ... 'Ascensionism' # Take to the broken skies at last ... ])}" 'This is the playlist: Take me back to Eden, Alkaline, Ascensionism'
Backslashes and unicode characters: before Python 3.12 f-string expressions couldn't contain any
\
character. This also affected unicode escape sequences (such as\N{snowman}
) as these contain the\N
part that previously could not be part of expression components of f-strings. Now, you can define expressions like this:>>> print(f"This is the playlist: {"\n".join(songs)}") This is the playlist: Take me back to Eden Alkaline Ascensionism >>> print(f"This is the playlist: {"\N{BLACK HEART SUIT}".join(songs)}") This is the playlist: Take me back to Eden♥Alkaline♥Ascensionism
更多细节请参见 PEP 701。
As a positive side-effect of how this feature has been implemented (by parsing f-strings
with the PEG parser, now error messages for f-strings are more precise
and include the exact location of the error. For example, in Python 3.11, the following
f-string raises a SyntaxError
:
>>> my_string = f"{x z y}" + f"{1 + 1}"
File "<stdin>", line 1
(x z y)
^^^
SyntaxError: f-string: invalid syntax. Perhaps you forgot a comma?
但是错误消息不包括错误在行中的确切位置,而且表达式被人为地用括号括起来。在Python 3.12中,由于f-字符串是用PEG解析器解析的,因此错误消息可以更精确,并显示整行:
>>> my_string = f"{x z y}" + f"{1 + 1}"
File "<stdin>", line 1
my_string = f"{x z y}" + f"{1 + 1}"
^^^
SyntaxError: invalid syntax. Perhaps you forgot a comma?
(由 Pablo Galindo、Batuhan Taskaya、 Lysandros Nikolaou、Cristián Maureira-Fredes 和 Marta Gómez 在 gh-102856 中贡献。 PEP 由 Pablo Galindo、 Batuhan Taskaya、 Lysandros Nikolaou 和 Marta Gómez 撰写)。
PEP 709:推导式内联¶
Dictionary, list, and set comprehensions are now inlined, rather than creating a new single-use function object for each execution of the comprehension. This speeds up execution of a comprehension by up to two times. See PEP 709 for further details.
Comprehension iteration variables remain isolated and don't overwrite a variable of the same name in the outer scope, nor are they visible after the comprehension. Inlining does result in a few visible behavior changes:
回溯中的推导式不再有单独的帧,跟踪/评测也不再将推导式显示为函数调用。
symtable
模块将不再为每个推导式产生子符号表;取而代之的是,推导式的 locals 将包括在父函数的符号表中。在推导式内部调用
locals()
现在包括该推导式外部外部的变量,而不再包括推导式“参数”导致的.0
合成变量。一个直接迭代
locals()
的推导式 (例如[k for k in locals()]
) 在启动追踪 (例如检测代码覆盖度) 的情况下运行时可能导致 "RuntimeError: dictionary changed size during iteration"。 此行为与现有的for k in locals():
等代码保持一致。 要避免此错误,可先创建一个由键组成的列表用于迭代:keys = list(locals()); [k for k in keys]
。
(Contributed by Carl Meyer and Vladimir Matveev in PEP 709.)
PEP 688: 使缓冲区协议在Python中可访问¶
PEP 688 引入了一种在 Python 代码中使用 缓冲区协议 的方法。实现 __buffer__()
方法的类现在可以作为缓冲区类型使用。
新的 collections.abc.Buffer
ABC(抽象基类)提供了一种表示缓冲区对象的标准方法,例如在类型注释中。 新的 inspect.BufferFlags
枚举表示可用于自定义缓冲区创建的标志。 (由 Jelle Zijlstra 在 gh-102500 中贡献。)
PEP 684: 解释器级 GIL¶
PEP 684 introduces a per-interpreter GIL, so that sub-interpreters may now be created with a unique GIL per interpreter. This allows Python programs to take full advantage of multiple CPU cores. This is currently only available through the C-API, though a Python API is anticipated for 3.13.
使用新的 Py_NewInterpreterFromConfig()
函数来创建具有单独 GIL 的解释器:
PyInterpreterConfig config = {
.check_multi_interp_extensions = 1,
.gil = PyInterpreterConfig_OWN_GIL,
};
PyThreadState *tstate = NULL;
PyStatus status = Py_NewInterpreterFromConfig(&tstate, &config);
if (PyStatus_Exception(status)) {
return -1;
}
/* The new interpeter is now active in the current thread. */
有关如何将 C-API 用于子解释器和解释器级 GIL 的更多示例,请参见 Modules/_xxsubinterpretersmodule.c。
(由 Eric Snow 在 gh-104210 等中贡献。)
PEP 669:针对 CPython 的低影响监控¶
PEP 669 defines a new API
for profilers,
debuggers, and other tools to monitor events in CPython.
It covers a wide range of events, including calls,
returns, lines, exceptions, jumps, and more.
This means that you only pay for what you use, providing support
for near-zero overhead debuggers and coverage tools.
See sys.monitoring
for details.
(Contributed by Mark Shannon in gh-103083.)
其他语言特性修改¶
Add support for the perf profiler through the new environment variable
PYTHONPERFSUPPORT
and command-line option-X perf
, as well as the newsys.activate_stack_trampoline()
,sys.deactivate_stack_trampoline()
, andsys.is_stack_trampoline_active()
functions. (Design by Pablo Galindo. Contributed by Pablo Galindo and Christian Heimes with contributions from Gregory P. Smith [Google] and Mark Shannon in gh-96123.)The extraction methods in
tarfile
, andshutil.unpack_archive()
, have a new a filter argument that allows limiting tar features than may be surprising or dangerous, such as creating files outside the destination directory. See tarfile extraction filters for details. In Python 3.14, the default will switch to'data'
. (Contributed by Petr Viktorin in PEP 706.)如果底层映射是可哈希的,那么
types.MappingProxyType
实例现在是可哈希的。 (由 Serhiy Storchaka 在 gh-87995 中贡献。)memoryview
现在支持半浮点类型(“e”格式代码)。 (由 Dong-hee Na 和 Antoine Pitrou 在 gh-90751 中贡献。)解析器现在在解析包含空字节的源代码时引发
SyntaxError
。 (由 Pablo Galindo 在 gh-96670 中贡献 。)ast.parse()
现在会在解析包含空字节的源代码时引发SyntaxError
而不是ValueError
。 (由 Pablo Galindo 在 gh-96670 中贡献 。)垃圾回收器现在只在 Python 字节码评估循环的 eval-breaker 机制上运行,而不是在对象分配上运行。 垃圾回收也可以在调用
PyErr_CheckSignals()
时运行,因此需要长时间运行而不执行任何 Python 代码的 C 扩展也有机会定期执行垃圾回收。 (由 Pablo Galindo 在 gh-97922 中贡献。)A backslash-character pair that is not a valid escape sequence now generates a
SyntaxWarning
, instead ofDeprecationWarning
. For example,re.compile("\d+\.\d+")
now emits aSyntaxWarning
("\d"
is an invalid escape sequence, use raw strings for regular expression:re.compile(r"\d+\.\d+")
). In a future Python version,SyntaxError
will eventually be raised, instead ofSyntaxWarning
. (Contributed by Victor Stinner in gh-98401.)值大于
0o377
(例如:"\477"
) 的八进制转义序列,在 Python 3.11 中已弃用,现在会产生SyntaxWarning
,而不是DeprecationWarning
。 在未来的 Python 版本中,它们最终将是SyntaxError
。 (由 Victor Stinner 在 gh-98401 中贡献。)所有期望布尔参数的内置和扩展可调用函数现在都接受任何类型的参数,而不仅仅是
bool
和int
。 (由 Serhiy Storchaka 在 gh-60203 中贡献。)未存储在推导式目标部分中的变量现在可以在赋值表达式 (
:=
) 中使用。 例如,在[(b := 1) for a, b.prop in some_iter]
中,现在允许对b
进行赋值。 请注意,根据 PEP 572,仍然不允许向存储在推导式目标部分中的变量 (如a
) 赋值。 (由 Nikita Sobolev 在 gh-100581 中贡献。)slice
对象现在是可哈希的,允许它们用作字典的键和集合项。 (由 Will Bradshaw、Furkan Onder 和 Raymond Hettinger 在 gh-101264 中贡献。)sum()
现在使用 Neumaier 求和来提高浮点求和或整数浮点混合求和的准确性。 (由 Raymond Hettinger 在 gh-100425 中贡献。)Exceptions raised in a class or type's
__set_name__
method are no longer wrapped by aRuntimeError
. Context information is added to the exception as a PEP 678 note. (Contributed by Irit Katriel in gh-77757.)当
try-except*
构造处理整个ExceptionGroup
并引发另一个异常时,该异常不再封装在ExceptionGroup
中。 在 3.11.4 版中也进行了更改。 (由 Irit Katriel 在 gh-103590 中贡献。)
新增模块¶
无。
改进的模块¶
array¶
array.array
类现在支持下标,使其成为 generic type。 (由 Jelle Zijlstra 在 gh-98658 中贡献。)
asyncio¶
在
asyncio
中写入套接字的性能得到了显著提高。asyncio
现在可以避免在写入套接字时进行不必要的复制,并在平台支持的情况下使用sendmsg()
。 (由 Kumar Aditya 在 gh-91166 中贡献。)Added
asyncio.eager_task_factory()
andasyncio.create_eager_task_factory()
functions to allow opting an event loop in to eager task execution, making some use-cases 2x to 5x faster. (Contributed by Jacob Bower & Itamar Oren in gh-102853, gh-104140, and gh-104138)On Linux,
asyncio
usesasyncio.PidfdChildWatcher
by default ifos.pidfd_open()
is available and functional instead ofasyncio.ThreadedChildWatcher
. (Contributed by Kumar Aditya in gh-98024.)The child watcher classes
asyncio.MultiLoopChildWatcher
,asyncio.FastChildWatcher
,asyncio.AbstractChildWatcher
andasyncio.SafeChildWatcher
are deprecated and will be removed in Python 3.14. It is recommended to not manually configure a child watcher as the event loop now uses the best available child watcher for each platform (asyncio.PidfdChildWatcher
if supported andasyncio.ThreadedChildWatcher
otherwise). (Contributed by Kumar Aditya in gh-94597.)asyncio.set_child_watcher()
、asyncio.get_child_watcher()
、asyncio.AbstractEventLoopPolicy.set_child_watcher()
和asyncio.AbstractEventLoopPolicy.get_child_watcher()
已弃用,并将在 Python 3.14 中移除。(由 Kumar Aditya 在 gh-94597 中贡献。)为
asyncio.run()
添加了形参 loop_factory,以允许指定自定义事件循环工厂。 (由 Kumar Aditya 在 gh-99388 中贡献。)Add C implementation of
asyncio.current_task()
for 4x-6x speedup. (Contributed by Itamar Oren and Pranav Thulasiram Bhat in gh-100344.)asyncio.iscoroutine()
现在为生成器返回False
,因为asyncio
不支持传统的基于生成器的协程。 (由 Kumar Aditya 在 gh-102748 中贡献。)asyncio.wait()
和asyncio.as_completed()
现在接受生成器 yield 任务。 (由 Kumar Aditya 在 gh-78530 中贡献。)
calendar¶
Add enums
calendar.Month
andcalendar.Day
defining months of the year and days of the week. (Contributed by Prince Roshan in gh-103636.)
csv¶
Add
csv.QUOTE_NOTNULL
andcsv.QUOTE_STRINGS
flags to provide finer grained control ofNone
and empty strings bycsv.writer
objects.
dis¶
Pseudo instruction opcodes (which are used by the compiler but do not appear in executable bytecode) are now exposed in the
dis
module.HAVE_ARGUMENT
is still relevant to real opcodes, but it is not useful for pseudo instructions. Use the newdis.hasarg
collection instead. (Contributed by Irit Katriel in gh-94216.)
fractions¶
类型为
fractions.Fraction
的对象现在支持浮点格式。 (由 Mark Dickinson 在 gh-100161 中贡献。)
importlib.resources¶
importlib.resources.as_file()
现在将支持资源目录。 (由 Jason R. Coombs 在 gh-97930 中贡献。)
inspect¶
添加
inspect.markcoroutinefunction()
来标记返回 coroutine 的同步函数,以便与inspect.iscoroutinefunction()
一起使用。 (由 Carlton Gibson 在 gh-99247 中贡献。)添加
inspect.getasyncgenstate()
和inspect.getasyncgenlocals()
来确定异步生成器的当前状态。 (由 Thomas Krennwallner 在 bpo-35759 中贡献。)inspect.getattr_static()
的性能得到了相当大的改进。 对函数的大多数调用应该比 Python 3.11 中至少快 2 倍,有些可能快 6 倍甚至更多。 (由 Alex Waygood 在 gh-103193 中贡献。)
itertools¶
增加了
itertools.batched()
用来收集到相同大小的元组其中最后一个批次的长度可能会比其他批次的短。 (由 Raymond Hettinger 在 gh-98363 中贡献。)
math¶
添加了
math.sumprod()
用于计算乘积的和。 (由 Raymond Hettinger 在 gh-100485 中贡献。)扩展了
math.nextafter()
以包含一个 steps 参数,用于一次上移或下移多个步骤。 (由 Matthias Goergens、Mark Dickinson 和 Raymond Hettinger在 gh-94906 中贡献。)
os¶
增加了
os.PIDFD_NONBLOCK
以在非阻塞模式下打开具有os.pidfd_open()
的进程的文件描述符。 (由 Kumar Aditya 在 gh-93312 中贡献。)os.DirEntry
现在包括一个os.DirEntry.is_junction()
方法来检查该条目是否为目录联接。 (由 Charles Machalow 在 gh-99547 中贡献。)在 Windows 版中添加
os.listdrives()
、os.listvolumes()
和os.listmounts()
函数,用于枚举驱动器、卷和挂载点。 (由 Steve Dower 在 gh-102519 中贡献。)os.stat()
和os.lstat()
现在在 Windows 系统上更准确了。st_birthtime
字段现在将使用文件的创建时间,st_ctime
已弃用,但仍包含创建时间(但为了与其他平台保持一致,将来将返回最后一次元数据更改时间)。st_dev
可以高达 64 位,st_ino
可以高达 128 位,具体取决于你的文件系统,并且st_rdev
始终设置为零,而非不正确的值。 这两个函数在较新版本的 Windows 上将会明显更快。 (由 Steve Dower 在 gh-99726 中贡献。)
os.path¶
添加
os.path.isjunction()
以检查给定路径是否为目录联接。 (由 Charles Machalow 在 gh-99547 中贡献。)添加
os.path.splitroot()
以将路径拆分为三元组(drive, root, tail)
。(由 Barney Gale 在 gh-101000 中贡献。)
pathlib¶
Add support for subclassing
pathlib.PurePath
andpathlib.Path
, plus their Posix- and Windows-specific variants. Subclasses may override thepathlib.PurePath.with_segments()
method to pass information between path instances.Add
pathlib.Path.walk()
for walking the directory trees and generating all file or directory names within them, similar toos.walk()
. (Contributed by Stanislav Zmiev in gh-90385.)添加可选形参 walk_up 到
pathlib.PurePath.relative_to()
,以允许在结果中插入..
条目;此行为更符合os.path.relpath()
。 (由 Domenico Ragusa 在 bpo-40358 中贡献。)添加
pathlib.Path.is_junction()
作为os.path.isjunction()
的代理。 (由 Charles Machalow 在 gh-99547 中贡献。)为
pathlib.Path.glob()
、pathlib.Path.rglob()
和pathlib.PurePath.match()
添加可选形参 case_sensitive,以匹配路径的大小写敏感性,从而对匹配过程进行更精确的控制。
pdb¶
添加便利变量以临时保存调试会话的值,并提供对当前帧或返回值等值的快速访问。 (由高天在 gh-103693 中贡献。)
random¶
添加了
random.binomialvariate()
。 (由 Raymond Hettinger 在 gh-81620 中贡献。)在
random.expovariate()
中添加了一个默认值lamb=1.0
。 (由 Raymond Hettinger 在 gh-100234 中贡献。)
shutil¶
shutil.make_archive()
现在将 rootdir 参数传递给支持它的自定义存档程序。 在这种情况下,它不再临时将进程的当前工作目录更改为 rootdir 来执行存档。 (由 Serhiy Storchaka 在 gh-74696 中贡献。)shutil.rmtree()
现在接受一个新的参数 onexc ,它是一个类似 onerror 的错误处理器,但它需要一个异常实例,而不是一个 (typ, val, tb) 三元组。 onerror 已弃用,并将在 Python 3.14 中移除。 (由 Irit Katriel 在 gh-102828 中贡献。)shutil.which()
现在即使给定的 cmd 包含目录组件,在 Windows 系统上也会参考 PATHEXT 环境变量在 PATH 中查找匹配项。 (由 Charles Machalow 在 gh-103179 中贡献。)shutil.which()
将在 Windows 上查询可执行文件时调用NeedCurrentDirectoryForExePathW
,以确定是否应将当前工作目录预先设置为搜索路径。 (由 Charles Machalow 在 gh-103179 中贡献。)在 Windows 上
shutil.which()
将在搜索路径的其他地方直接匹配之前返回 cmd 与来自PATHEXT
的组件相匹配的路径。 (由 Charles Machalow 在 gh-103179 中贡献。)
sqlite3¶
Add the
sqlite3.Connection.autocommit
attribute tosqlite3.Connection
and the autocommit parameter tosqlite3.connect()
to control PEP 249-compliant transaction handling. (Contributed by Erlend E. Aasland in gh-83638.)Add entrypoint keyword-only parameter to
sqlite3.Connection.load_extension()
, for overriding the SQLite extension entry point. (Contributed by Erlend E. Aasland in gh-103015.)Add
sqlite3.Connection.getconfig()
andsqlite3.Connection.setconfig()
tosqlite3.Connection
to make configuration changes to a database connection. (Contributed by Erlend E. Aasland in gh-103489.)
statistics¶
扩展了
statistics.correlation()
以ranked
方法的形式来包括对分级数据的斯皮尔曼相关性计算。 (由 Raymond Hettinger 在 gh-95861 中贡献。)
sys¶
增加了
sys.activate_stack_trampoline()
和sys.deactivate_stack_trampoline()
用于激活和停用栈性能分析器 trampoline,以及sys.is_stack_trampoline_active()
用于查询栈性能分析器 trampoline 是否激活。 (基于 Gregory P. Smith [Google] 和 Mark Shannon 的贡献由 Pablo Galindo 和 Christian Heimes 在 gh-96123 中贡献。)增加了
sys.last_exc
用于保存最新引发的未处理异常(针对事后调试的应用场景)。 弃用了以三个字段来保存相同信息的旧形式:sys.last_type
,sys.last_value
和sys.last_traceback
。 (由 Irit Katriel 在 gh-102778 中贡献。)现在
sys._current_exceptions()
将返回从线程 ID 到异常实例的映射,而不是到(typ, exc, tb)
元组的映射。 (由 Irit Katriel 在 gh-103176 中贡献。)sys.setrecursionlimit()
和sys.getrecursionlimit()
。 递归限制现在只应用于 Python 代码。 内置函数不使用该递归限制,但受到另一种可防止递归导致虚拟机崩溃的机制保护。
tempfile¶
tempfile.NamedTemporaryFile
函数增加了一个新的可选形参 delete_on_close。 (由 Evgeny Zorin 在 gh-58451 中贡献。)tempfile.mkdtemp()
现在将总是返回一个绝对路径,即使提供给 dir 形参的参数是一个相对路径。
threading¶
增加了
threading.settrace_all_threads()
和threading.setprofile_all_threads()
以允许在所运行的全部线程中设置追踪和性能分析函数而不是只在调用方线程中。 (由 Pablo Galindo 在 gh-93503 中贡献。)
tkinter¶
现在
tkinter.Canvas.coords()
会展平其参数。 它现在不仅接受单独参数形式的坐标 (x1, y1, x2, y2, ...
) 以及由坐标组成的序列 ([x1, y1, x2, y2, ...]
),也接受成对分组 ((x1, y1), (x2, y2), ...
和[(x1, y1), (x2, y2), ...]
) 形式的坐标,就像create_*()
方法一样。 (由 Serhiy Storchaka 在 gh-94473 中贡献。)
tokenize¶
The
tokenize
module includes the changes introduced in PEP 701. (Contributed by Marta Gómez Macías and Pablo Galindo in gh-102856.) See 移植到 Python 3.12 for more information on the changes to thetokenize
module.
types¶
增加了
types.get_original_bases()
以允许在子类化时继续对 用户定义的泛型类型 进行内省。 (由 James Hilton-Balfe 和 Alex Waygood 在 gh-101827 中贡献。)
typing¶
针对
运行时可检测协议
的isinstance()
检测现在会使用inspect.getattr_static()
而不是hasattr()
来查找属性是否存在。 这意味着描述器和__getattr__()
方法在针对运行时可检测协议的isinstance()
检测期间不会被意外地求值。 但是,这也意味着某些原来被视为运行时可检测协议的实例的对象在 Python 3.12+ 上将不再被视为运行时可检测协议的实例,反之亦然。 大部分用户都不太可能受到这一改变的影响。 (由 Alex Waygood 在 gh-102433 中贡献。)现在运行时可检测协议的成员在运行时一旦创建了相应的类就将被视为“已冻结”。 作用于运行时可检测协议的猴子补丁属性将仍然可用,但不会再影响将对象与协议进行比较的
isinstance()
检测中。 例如:>>> from typing import Protocol, runtime_checkable >>> @runtime_checkable ... class HasX(Protocol): ... x = 1 ... >>> class Foo: ... ... >>> f = Foo() >>> isinstance(f, HasX) False >>> f.x = 1 >>> isinstance(f, HasX) True >>> HasX.y = 2 >>> isinstance(f, HasX) # unchanged, even though HasX now also has a "y" attribute True
应用这项改变是为了提高针对运行时可检测协议的
isinstance()
检测速度。针对
运行时可检测协议
的isinstance()
检测的性能表现有显著的改进。 对于具有少量成员的协议的isinstance()
检测相比 3.11 应当至少有 2x 的提速,有些可能会有 20x 或更多的提速。 但是,对于具有十四个或更多成员的协议的isinstance()
检测可能会慢于 Python 3.11。 (由 Alex Waygood 在 gh-74690 和 gh-103193 中贡献。)现在所有
typing.TypedDict
和typing.NamedTuple
类都具有__orig_bases__
属性。 (由 Adrian Garcia Badaracco 在 gh-103699 中贡献。)向
typing.dataclass_transform()
添加了frozen_default
形参。 (由 Erik De Bonte 在 gh-99957 中贡献。)
unicodedata¶
Unicode 数据库已更新到 15.0.0 版。 (由 Benjamin Peterson 在 gh-96734 中贡献。)
unittest¶
增加了 --durations
命令行选项,显示 N 个最慢的测试用例:
python3 -m unittest --durations=3 lib.tests.test_threading
.....
Slowest test durations
----------------------------------------------------------------------
1.210s test_timeout (Lib.test.test_threading.BarrierTests)
1.003s test_default_timeout (Lib.test.test_threading.BarrierTests)
0.518s test_timeout (Lib.test.test_threading.EventTests)
(0.000 durations hidden. Use -v to show these durations.)
----------------------------------------------------------------------
Ran 158 tests in 9.869s
OK (skipped=3)
(由 Giampaolo Rodola 在 bpo-4080 中贡献。)
uuid¶
性能优化¶
从 Unicode 对象中移除了
wstr
和wstr_length
成员。 这使得对象大小在 64 位平台上减小了 8 个或 16 个字节。 (PEP 623) (由 Inada Naoki 在 gh-92536 中贡献。)增加了在构建进程中使用 BOLT 二进制优化器的试验性支持,这将使使性能提升 1-5%。 (由 Kevin Modzelewski 在 gh-90536 中贡献并由 Dong-hee Na 在 gh-101525 中加以改进。)
对于包含分组引用的替换字符串的正则表达式替换(包括
re.sub()
和re.subn()
函数及对应的re.Pattern
方法)可加速 2--3 倍。 (由 Serhiy Storchaka 在 gh-91524 中贡献。)Speed up
asyncio.Task
creation by deferring expensive string formatting. (Contributed by Itamar Oren in gh-103793.)作为在
tokenize
模块中应用 PEP 701 所要求的更改的附带效果,tokenize.tokenize()
和tokenize.generate_tokens()
函数可加速至多 64%。 (由 Marta Gómez Macías 和 Pablo Galindo 在 gh-102856 中贡献。)通过新的
LOAD_SUPER_ATTR
指令加速super()
方法调用和属性加载。 (由 Carl Meyer 和 Vladimir Matveev 在 gh-103497 中贡献。)
CPython 字节码的改变¶
Remove the
LOAD_METHOD
instruction. It has been merged intoLOAD_ATTR
.LOAD_ATTR
will now behave like the oldLOAD_METHOD
instruction if the low bit of its oparg is set. (Contributed by Ken Jin in gh-93429.)移除了
JUMP_IF_FALSE_OR_POP
和JUMP_IF_TRUE_OR_POP
指令。 (由 Irit Katriel 在 gh-102859 中贡献。)移除了
PRECALL
指令。 (由 Mark Shannon 在 gh-92925 中贡献。)增加了
LOAD_FAST_AND_CLEAR
指令作为 PEP 709 的实现的组成部分。 (由 Carl Meyer 在 gh-101441 中贡献。)增加了
LOAD_FROM_DICT_OR_DEREF
,LOAD_FROM_DICT_OR_GLOBALS
和LOAD_LOCALS
操作码作为 PEP 695 的组成部分。 移除了LOAD_CLASSDEREF
操作码,它可以用LOAD_LOCALS
加LOAD_FROM_DICT_OR_DEREF
来代替。 (由 Jelle Zijlstra 在 gh-103764 中贡献。)增加了
LOAD_SUPER_ATTR
指令。 (由 Carl Meyer 和 Vladimir Matveev 在 gh-103497 中贡献。)
演示和工具¶
移除了包含旧演示脚本的
Tools/demo/
目录。 其副本可在 old-demos project 中找到。 (由 Victor Stinner 在 gh-97681 中贡献。)移除了
Tools/scripts/
目录下过时的示例脚本。 其副本可在 old-demos project 中找到。 (由 Victor Stinner 在 gh-97669 中贡献。)
弃用¶
asyncio
: 现在默认事件循环策略的get_event_loop()
方法在当前事件循环未设置并决定创建一个时将发出DeprecationWarning
。 (由 Serhiy Storchaka 和 Guido van Rossum 在 gh-100160 中贡献。)calendar
:calendar.January
和calendar.February
常量已被弃用并由calendar.JANUARY
和calendar.FEBRUARY
替代。 (由 Prince Roshan 在 gh-103636 中贡献。)datetime
:datetime.datetime
的utcnow()
和utcfromtimestamp()
已被弃用并将在未来的版本中移除。 请改用可感知时区的对象以 UTC 来表示日期时间:分别调用now()
和fromtimestamp()
并设置 tz 形参为datetime.UTC
。 (由 Paul Ganssle 在 gh-103857 中贡献。)os
: 在 Windows 上由os.stat()
和os.lstat()
返回的st_ctime
字段已被弃用。 在未来的版本中,它们将包含最近的元数据修改时间,以与其他平台保持一致。 目前,它们仍然包含创建时间,该值也可通过新的st_birthtime
字段获取。 (由 Steve Dower 在 gh-99726 中贡献。)shutil
:shutil.rmtree()
的 onerror 参数已被弃用并将在 Python 3.14 中移除。 请改用 onexc。 (由 Irit Katriel 在 gh-102828 中贡献。)sqlite3
:默认适配器和转换器 现在已被弃用,请使用 适配器和转换器范例程序 并根据你的需要调整它们。 (由 Erlend E. Aasland 在 gh-90016 中贡献。)
在
execute()
中,现在当 命名占位符 与作为 sequence 而不是dict
提供的形参一起使用时将发出DeprecationWarning
。 从 Python 3.14 开始,当命名占位符与作为序列提供的形参一起使用时将引发ProgrammingError
。 (由 Erlend E. Aasland 在 gh-101698 中贡献。)
sys
:sys.last_type
,sys.last_value
和sys.last_traceback
字段已被弃用。 请改用sys.last_exc
。 (由 Irit Katriel 在 gh-102778 中贡献。)tarfile
: 提取 tar 归档而不指定 filter 的做法已被弃用直到 Python 3.14,在该版本中'data'
将成为默认过滤器。 请参阅 解压缩过滤器 了解详情。typing
:typing.Hashable
和typing.Sized
是collections.abc.Hashable
和collections.abc.Sized
的别名。 (参见 gh-94309。)xml.etree.ElementTree
: 现在该模块在对xml.etree.ElementTree.Element
进行真值测试时将发出DeprecationWarning
。 在之前,Python 实现会发出FutureWarning
,而 C 实现则不会发出任何警告。throw()
,throw()
和athrow()
的 3 参数签名 (type, value, traceback) 已被弃用并可能在未来的 Python 版本中被移除。 请改用这些函数的单参数版本。 (由 Ofey Chan 在 gh-89874 中贡献。)现在当一个模块上的
__package__
不同于__spec__.parent
时将引发DeprecationWarning
(在之前版本中则为ImportWarning
)。 (由 Brett Cannon 在 gh-65961 中贡献。)根据 PEP 699 的要求,
PyDictObject
中的ma_version_tag
字段对于扩展模块已被弃用。 访问该字段将在编译时生成编译器警告。 该字段将在 Python 3.14 中移除。 (由 Ramvikrams 和 Kumar Aditya 在 gh-101193 中贡献。 PEP 由 Ken Jin 撰写。)用于布尔值的按位取反运算符 (
~
) 已被弃用。 它在 Python 3.14 中将抛出错误。 请改用not
执行布尔值的逻辑非运算。 在你确实需要对下层的int
执行取反运算的少数场景下,请显式地通过~int(x)
将其转换为整数值。 (由 Tim Hoffmann 在 gh-103487 中贡献。)
计划在 Python 3.13 中移除¶
以下模块和 API 已在之前的 Python 发布版中弃用,并将在 Python 3.13 中移除。
模块 (参见 PEP 594):
其他模块:
lib2to3
,以及 2to3 程序 (gh-84540)
API:
计划在 Python 3.14 中移除¶
argparse
:argparse.BooleanOptionalAction
的 type, choices 和 metavar 形参已被弃用并将在 3.14 中移除。 (由 Nikita Sobolev 在 gh-92248 中贡献。)ast
: 以下ast
特性自 Python 3.8 起已在文档中声明弃用,现在当运行时如果它们被访问或使用将发出DeprecationWarning
,并将在 Python 3.14 中移除:ast.Num
ast.Str
ast.Bytes
ast.NameConstant
ast.Ellipsis
请改用
ast.Constant
。 (由 Serhiy Storchaka 在 gh-90953 中贡献。)asyncio
:asyncio.Future.cancel()
和asyncio.Task.cancel()
的 msg 形参 (gh-90985)collections.abc
: 已弃用collections.abc.ByteString
。 推荐改用Sequence
或collections.abc.Buffer
。 在类型标中,推荐改用并集,如bytes | bytearray
或collections.abc.Buffer
。 (由 Shantanu Jain 在 gh-91896 中贡献。)email
: 已弃用email.utils.localtime()
中的 isdst 形参。 (由 Alan Williams 在 gh-72346 中贡献。)importlib.abc
: 已弃用下列类,计划在 Python 3.14 中移除:importlib.abc.ResourceReader
importlib.abc.Traversable
importlib.abc.TraversableResources
使用
importlib.resources.abc
类代替:(由 Jason R. Coombs 和 Hugo van Kemenade 在 gh-93963 中贡献。)
itertools
: 该模块具有对 copy, deepcopy 和 pickle 等操作的未写入文档的、低效的、历史上充满问题的且不稳定的支持。 这将在 3.14 中移除以显著减少代码量和维护负担。 (由 Raymond Hettinger 在 gh-101588 中贡献。)multiprocessing
: 默认的multiprocessing
启动方法在目前默认使用'fork'
的 Linux, BSD 和其他非 macOS 的 POSIX 平台上将改为更安全的启动方法 (gh-84559)。 为此添加运行时警告将带来糟糕的体验因为大部分代码并不会关心这个问题。 当你的代码 需要'fork'
时请使用get_context()
或set_start_method()
API 来显式地指明。 参见 上下文和启动方法。pkgutil
: 现在pkgutil.find_loader()
和pkgutil.get_loader()
将引发DeprecationWarning
;请改用importlib.util.find_spec()
。 (由 Nikita Sobolev 在 gh-97850 中贡献。)pty
: 该模块有两个未写入文档的master_open()
和slave_open()
函数自 Python 2 起即已被弃用但直到 3.12 才添加了相应的DeprecationWarning
。 它们将在 3.14 中移除。shutil
:shutil.rmtree()
的 onerror 参数在 3.12 中已被弃用,并将在 3.14 中移除。typing
:typing.ByteString
自 Python 3.9 起已被弃用,现在当被使用时将会发出DeprecationWarning
。xml.etree.ElementTree
: 已弃用对xml.etree.ElementTree.Element
进行真值测试并将在 Python 3.14 中引发异常。使用 C API 创建以可变类为基类的不可变类型 (
Py_TPFLAGS_IMMUTABLETYPE
) (gh-95388)。__package__
和__cached__
将不再被设置或是被导入系统纳入考量 (gh-97879)。对
co_lnotab
的访问自 3.10 起已在 PEP 626 中被弃用并原定在 3.12 中移除,但实际上在 3.12 中仅添加了DeprecationWarning
。 可能会在 3.14 中移除。 (由 Nikita Sobolev 在 gh-101866 中贡献。)
计划在未来版本中移除¶
下列 API 在更早的 Python 版本中已被弃用并将被移除,但目前还没有确定它们的移除日期。
移除¶
asynchat 和 asyncore¶
configparser¶
configparser
中的几个从 3.2 起已被弃用的名称已根据 gh-89336 被移除:configparser.ParsingError
不再具有filename
属性或参数。 请改用source
属性和参数。configparser
不再具有SafeConfigParser
类。 请改用更简短的名称ConfigParser
。configparser.ConfigParser
不再具有readfp
方法。 请改用read_file()
。
distutils¶
ensurepip¶
从
ensurepip
中移除了捆绑的 setuptools wheel,并停止在由venv
创建的环境中安装 setuptools。pip (>= 22.1)
不再要求在环境中安装 setuptools。 基于setuptools
(和基于distutils
) 的包仍然可通过pip install
来使用,因为 pip 将在它用于构建包的构建环境中提供setuptools
。在默认情况下由
venv
创建或通过ensurepip
初始化的环境将不再提供easy_install
,pkg_resources
,setuptools
和distutils
包,因为它们是setuptools
包的组成部分。 对于在运行时依赖这些包的项目,应当将setuptools
项目声明为依赖项之一并单独安装(通常是使用 pip)。(由 Pradyun Gedam 在 gh-95299 中贡献。)
enum¶
ftplib¶
gzip¶
移除了
gzip
中gzip.GzipFile
的filename
属性,自 Python 2.6 起该属性已被弃用,请改用name
属性。 在可写模式下,如果filename
属性没有'.gz'
文件扩展名则会添加它。 (由 Victor Stinner 在 gh-94196 中贡献。)
hashlib¶
移除了
hashlib
中hashlib.pbkdf2_hmac()
的纯 Python 实现,它在 Python 3.10 中已被弃用。 Python 3.10 及更新版本需要 OpenSSL 1.1.1 (PEP 644):该 OpenSSL 版本提供了pbkdf2_hmac()
的更快速的 C 实现。 (由 Victor Stinner 在 gh-94199 中贡献。)
importlib¶
importlib
中许多先前已弃用对象的清理工作现已完成:对
module_repr()
的引用和支持已被移除。 (由 Barry Warsaw 在 gh-97850 中贡献。)importlib.util.set_package
,importlib.util.set_loader
和importlib.util.module_for_loader
均已被移除。 (由 Brett Cannon 和 Nikita Sobolev 在 gh-65961 和 gh-97850 中贡献。)对
find_loader()
和find_module()
API 的支持已被移除。 (由 Barry Warsaw 在 gh-98040 中贡献。)importlib.abc.Finder
,pkgutil.ImpImporter
和pkgutil.ImpLoader
已被移除。 (由 Barry Warsaw 在 gh-98040 中贡献。)
imp¶
imp
模块已被移除。 (由 Barry Warsaw 在 gh-98040 中贡献。)将已移除的
imp
函数替换为importlib
函数:imp
importlib
imp.NullImporter
将
None
插入到sys.path_importer_cache
imp.cache_from_source()
imp.find_module()
imp.get_magic()
imp.get_suffixes()
importlib.machinery.SOURCE_SUFFIXES
,importlib.machinery.EXTENSION_SUFFIXES
和importlib.machinery.BYTECODE_SUFFIXES
imp.get_tag()
imp.load_module()
imp.new_module(name)
types.ModuleType(name)
imp.reload()
imp.source_from_cache()
将
imp.load_source()
替换为:import importlib.util import importlib.machinery def load_source(modname, filename): loader = importlib.machinery.SourceFileLoader(modname, filename) spec = importlib.util.spec_from_file_location(modname, filename, loader=loader) module = importlib.util.module_from_spec(spec) # The module is always executed and not cached in sys.modules. # Uncomment the following line to cache the module. # sys.modules[module.__name__] = module loader.exec_module(module) return module
已移除
imp
函数和属性并且没有替选项:未写入文档的函数:
imp.init_builtin()
imp.load_compiled()
imp.load_dynamic()
imp.load_package()
imp.lock_held()
,``imp.acquire_lock()``,``imp.release_lock()``: 加锁方案在 Python 3.3 中已改为模块级锁。imp.find_module()
常量:SEARCH_ERROR
,PY_SOURCE
,PY_COMPILED
,C_EXTENSION
,PY_RESOURCE
,PKG_DIRECTORY
,C_BUILTIN
,PY_FROZEN
,PY_CODERESOURCE
,IMP_HOOK
。
io¶
locale¶
sqlite3¶
以下未写入文档的
sqlite3
特性,在 Python 3.10 中已被弃用,现在已被移除:sqlite3.enable_shared_cache()
sqlite3.OptimizedUnicode
如果必须使用共享缓存,请在以 URI 模式打开数据库时使用
cache=shared
查询参数。sqlite3.OptimizedUnicode
文本工厂函数自 Python 3.3 起已成为str
的一个别名。 之前将文本工厂设为OptimizedUnicode
的代码可以显式地使用str
,或者依赖同样为str
的默认值。(由 Erlend E. Aasland 在 gh-92548 中贡献。)
ssl¶
移除了
ssl
的ssl.RAND_pseudo_bytes()
函数,它在 Python 3.6 中已被弃用:请改用os.urandom()
或ssl.RAND_bytes()
。 (由 Victor Stinner 在 gh-94199 中贡献。)移除了
ssl.match_hostname()
函数。 它在 Python 3.7 中已被弃用。 OpenSSL 自 Python 3.7 起将会执行主机名匹配,Python 已不再使用ssl.match_hostname()
函数。 (由 Victor Stinner 在 gh-94199 中贡献。)移除了
ssl.wrap_socket()
函数,它在 Python 3.7 中已被弃用:请改为创建一个ssl.SSLContext
对象并调用其ssl.SSLContext.wrap_socket
方法。 任何仍然使用ssl.wrap_socket()
的包都不再适用并且是不安全的。 该函数既不会发送 SNI TLS 扩展也不会验证服务器主机名。 其代码会受到 CWE-295: 不正确的证书验证问题的影响。 (由 Victor Stinner 在 gh-94199 中贡献。)
unittest¶
移除了许多早已弃用的
unittest
特性:一些
TestCase
方法的别名:已弃用的别名
方法名
弃用于
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
您可以使用 https://github.com/isidentical/teyit 来自动更新你的单元测试。
未写入文档且已不可用的
TestCase
方法assertDictContainsSubset
。 (在 Python 3.2 中已弃用。)未写入文档的
TestLoader.loadTestsFromModule
形参 use_load_tests。 (自 Python 3.2 起已弃用并被忽略。)TextTestResult
类的一个别名:_TextTestResult
。 (在 Python 3.2 中已弃用。)
(由 Serhiy Storchaka 在 bpo-45162 中贡献。)
webbrowser¶
从
webbrowser
移除了对过时浏览器的支持。 被移除的浏览器包括: Grail, Mosaic, Netscape, Galeon, Skipstone, Iceape, Firebird 和 Firefox 35 及以下的版本 (gh-102871)。
xml.etree.ElementTree¶
移除了纯 Python 实现的
ElementTree.Element.copy()
方法,该方法在 Python 3.10 中已被弃用,请改用copy.copy()
函数。xml.etree.ElementTree
的 C 实现没有copy()
方法,只有__copy__()
方法。 (由 Victor Stinner 在 gh-94383 中贡献。)
zipimport¶
其他事项¶
从文档 Makefile 中移除了
suspicious
规则,并移除了Doc/tools/rstlint.py
,请改用 sphinx-lint。 (由 Julien Palard 在 gh-98179 中贡献。)移除了
ftplib
、imaplib
、poplib
和smtplib
模块中的 keyfile 和 certfile 形参数,以及http.client
模块中的 key_file、cert_file 和 check_hostname 形参,它们自 Python 3.6 起都已被弃用。 请改用 context 形参(在imaplib
中为 ssl_context 形参)。 (由 Victor Stinner 在 gh-94172 中贡献。).)
移植到 Python 3.12¶
本节列出了先前描述的更改以及可能需要更改代码的其他错误修正.
Python API 的变化¶
现在对于正则表达式中的数字分组引用和分组名称将应用更严格的规则。 现在只接受 ASCII 数字序列作为数字引用。 字节串模式和替换字符串中的分组名称现在只能包含 ASCII 字母、数字和下划线。 (由 Serhiy Storchaka 在 gh-91760 中贡献。)
移除了自 Python 3.10 起已被弃用的
randrange()
功能。 以前,randrange(10.0)
会无损地转换为randrange(10)
。 现在,它将引发TypeError
。 此外,对于非整数值如randrange(10.5)
或randrange('10')
所引发的异常已从ValueError
改为TypeError
。 这也防止了randrange(1e25)
会从比randrange(10**25)
更大的范围中静默选择的问题。 (最初由 Serhiy Storchaka 在 gh-86388 中提议。)argparse.ArgumentParser
将从文件(例如fromfile_prefix_chars
选项)读取参数的编码格式和错误处理句柄从默认的文本编码格式(例如locale.getpreferredencoding(False)
调用)改为 filesystem encoding and error handler。 在 Windows 系统中参数文件应使用 UTF-8 而不是 ANSI 代码页来编码。删除了在 Python 3.4.7 和 3.5.4 中已被弃用的
asyncore
-basedsmtpd
模块。 推荐使用基于asyncio
的 aiosmtpd PyPI 模块来替代。shlex.split()
: 传入None
作为 s 参数现在将引发异常,而不是读取sys.stdin
。 该特性在 Python 3.9 中已被弃用。 (由 Victor Stinner 在 gh-94352 中贡献。)os
模块不再接受类似字节串的路径,如bytearray
和memoryview
类型:只接受明确的bytes
类型字节串。 (由 Victor Stinner 在 gh-98393 中贡献。)现在
syslog.openlog()
和syslog.closelog()
如果在子解释器中使用将失败。syslog.syslog()
仍可在子解释器中使用,但前提是syslog.openlog()
已在主解释器中被调用。 这些新限制不适用于主解释器,因此只有少数用户可能会受到影响。 这一改变有助于实现解释器隔离。 此外,syslog
是一个针对进程全局资源的包装器,而这些资源最好是通过主解释器来管理。 (由 Dong-hee Na 在 gh-99127 中贡献。)未写入文档的
cached_property()
的锁定行为已被移除,因为该行为会在类的所有实例中锁定,从而导致高锁定争用。 这意味着如果两个线程同时运行,缓存属性获取函数现在可以在单个实例中运行不止一次。 对于大多数简单的缓存属性(例如那些幂等的并且只需根据实例的其他属性计算一个值的属性)来说这是没有问题的。 如果需要同步,可在缓存属性获取函数中或多线程访问点周围实现锁定操作。现在
sys._current_exceptions()
将返回从线程 ID 到异常实例的映射,而不是到(typ, exc, tb)
元组的映射。 (由 Irit Katriel 在 gh-103176 中贡献。)当使用
tarfile
或shutil.unpack_archive()
提取 tar 文件时,请传入 filter 参数来限制可能令人感到意外或危险的特性。 请参阅 解压缩过滤器 了解详情。由于在 PEP 701 中引入的更改
tokenize.tokenize()
和tokenize.generate_tokens()
函数的输出现在发生了改变。 这意味着不再为 f-字符输出STRING
词元而是改为产生 PEP 701 中描述的词元:除了用于对表达式组件进行分词的适当词元外现在还有FSTRING_START
,FSTRING_MIDDLE
和FSTRING_END
会被用于 f-字符串的“字符串”部分。 例如对于 f-字符串f"start {1+1} end"
旧版本的分词器会生成:1,0-1,18: STRING 'f"start {1+1} end"'
而新版本将生成:
1,0-1,2: FSTRING_START 'f"' 1,2-1,8: FSTRING_MIDDLE 'start ' 1,8-1,9: OP '{' 1,9-1,10: NUMBER '1' 1,10-1,11: OP '+' 1,11-1,12: NUMBER '1' 1,12-1,13: OP '}' 1,13-1,17: FSTRING_MIDDLE ' end' 1,17-1,18: FSTRING_END '"'
此外,支持 PEP 701 所需的改变还可能会导致一些细微的行为改变。 这些变化包括:
在对一些无效 Python 字符如
!
进行分词时相应词元的type
属性已从ERRORTOKEN
变为OP
。不完整的单行字符串现在也会像不完整的多行字符串一样引发
tokenize.TokenError
。某些不完整或无效的 Python 代码现在会引发
tokenize.TokenError
而不是在执行分词时返回任意的ERRORTOKEN
词元。在同一文件中混合使用制表符和空格作为缩进不再受到支持而是会引发
TabError
。
构建变化¶
Python 不再使用
setup.py
来构建共享的 C 扩展模块。 头文件和库等编译参数会在configure
脚本中检测。 扩展将由Makefile
来构建。 大多数扩展使用pkg-config
并回退为手动检测。 (由 Christian Heimes 在 gh-93939 中贡献。)现在需要用带有两个形参的
va_start()
,如va_start(args, format),
来构建 Python。 现在将不会再调用单个形参的va_start()
。 (由 Kumar Aditya 在 gh-93207 中贡献。)现在如果 Clang 编译器接受 ThinLTO 选项则 CPython 会将其作为默认的链接时间优化策略。 (由 Dong-hee Na 在 gh-89536 中贡献。)
在 Makefile 中添加了
COMPILEALL_OPTS
变量以覆盖make install
中的compileall
选项 (默认值:-j0
)。 并将 3 条compileall
命令合并为单条命令以便一次性构建所有优化级别 (0, 1, 2) 的 .pyc 文件。 (由 Victor Stinner 在 gh-99289 中贡献。)为 64 位 LoongArch 添加了平台三选项:
loongarch64-linux-gnusf
loongarch64-linux-gnuf32
loongarch64-linux-gnu
(由 Zhang Na 在 gh-90656 中贡献。).)
PYTHON_FOR_REGEN
现在需要 Python 3.10 或更新版本。现在需要有 autoconf 2.71 和 aclocal 1.16.4 才能重新生成
!configure
。 (由 Christian Heimes 在 gh-89886 中贡献。)来自 python.org 的 Windows 版本和 macOS 安装程序现在使用 OpenSSL 3.0。
C API 的变化¶
新的特性¶
PEP 697: 引入了 不稳定 C API 层,用于调试器和 JIT 编译器等低层级工具。 该 API 可能会在 CPython 的每个次要版本中发生变化而不发出弃用警告。 其内容在名称中会以
PyUnstable_
前缀标记。代码对象构造器:
PyUnstable_Code_New()
(由PyCode_New
改名而来)PyUnstable_Code_NewWithPosOnlyArgs()
(由PyCode_NewWithPosOnlyArgs
改名而来)
代码对象的额外存储 (PEP 523):
PyUnstable_Eval_RequestCodeExtraIndex()
(由_PyEval_RequestCodeExtraIndex
改名而来)PyUnstable_Code_GetExtra()
(由_PyCode_GetExtra
改名而来)PyUnstable_Code_SetExtra()
(由_PyCode_SetExtra
改名而来)
原有名称将继续可用直到对应的 API 发生改变。
(由 Petr Viktorin 在 gh-101101 中贡献。)
PEP 697: 添加了用于扩展实例的内存布局不透明的 API:
PyType_Spec.basicsize
可以为零或负数,用于以指定继承或扩展基类的大小。增加了
PyObject_GetTypeData()
和PyType_GetTypeDataSize()
以允许访问特定子类的实例数据。添加了
Py_TPFLAGS_ITEMS_AT_END
和PyObject_GetItemData()
以允许安全地扩展某些可变大小的类型,包括PyType_Type
。添加了
Py_RELATIVE_OFFSET
以允许用特定于子类的结构体来定义成员
。
(由 Petr Viktorin 在 gh-103509 中贡献。)
添加了新的 受限 C API 函数
PyType_FromMetaclass()
,它使用额外的 metaclass 参数对现有的PyType_FromModuleAndSpec()
进行了泛化。 (由 Wenzel Jakob 在 gh-93012 中贡献。)在 受限 中添加了用于创建可使用 vectorcall 协议 来调用的对象的 API:
现在当一个类的
__call__()
方法被重新赋值时,该类的Py_TPFLAGS_HAVE_VECTORCALL
旗标将被移除。 这使得 vectorcall 可以安全地用于可变类型(即没有不可变旗标Py_TPFLAGS_IMMUTABLETYPE
的堆类型)。 未重载tp_call
的可变类型现在继承了Py_TPFLAGS_HAVE_VECTORCALL
旗标。 (由 Petr Viktorin 在 gh-93274 中贡献。)新增了
Py_TPFLAGS_MANAGED_DICT
和Py_TPFLAGS_MANAGED_WEAKREF
旗标。 这将允许扩展类在支持对象__dict__
和弱引用时减少记录消耗,占用更少内存并并加快访问速度。在 受限 API 中添加了使用 vectorcall 协议 执行调用的 API:
这意味着 vectorcall 调用协议的传入端和传出端现在都可以在 受限 API 中使用。 (由 Wenzel Jakob 在 gh-98586 中贡献。)
添加了两个新的公共函数
PyEval_SetProfileAllThreads()
和PyEval_SetTraceAllThreads()
,允许在调用的同时在所有运行线程中设置追踪和性能分析函数。 (由 Pablo Galindo 在 gh-93503 贡献。)为 C API 添加了新函数
PyFunction_SetVectorcall()
用于设置给定PyFunctionObject
的 vectorcall 字段。 (由 Andrew Frost 在 gh-92257 中贡献。)C API 现在允许通过
PyDict_AddWatcher()
、PyDict_Watch()
和相关 API 注册回调,以便在字典被修改时调用。 这主要用于优化解释器、JIT 编译器或调试器。 (由 Carl Meyer 在 gh-91052 中贡献。)添加了
PyType_AddWatcher()
和PyType_Watch()
API 用于注册回调以接收类型变更通知。 (由 Carl Meyer 在 gh-91051 中贡献。)Added
PyCode_AddWatcher()
andPyCode_ClearWatcher()
APIs to register callbacks to receive notification on creation and destruction of code objects. (Contributed by Itamar Oren in gh-91054.)添加了
PyFrame_GetVar()
和PyFrame_GetVarString()
函数用于通过名称来获取帧变量。 (由 Victor Stinner 在 gh-91248 中贡献。)添加
PyErr_GetRaisedException()
和PyErr_SetRaisedException()
用于保存和恢复当前异常。 这些函数返回并接受单个异常对象,而不是像现在已弃用的PyErr_Fetch()
和PyErr_Restore()
那样的三个参数。 这样不容易出错并且更为高效。 (由 Mark Shannon 在 gh-101578 中贡献。)添加了
_PyErr_ChainExceptions1
,它接受一个异常实例,用于取代旧式 API_PyErr_ChainExceptions
,后者现已被弃用。 (由 Mark Shannon 在 gh-101578 中贡献。)添加了
PyException_GetArgs()
和PyException_SetArgs()
作为便捷函数用于检索和修改传递给异常的构造函数的args
。 (由 Mark Shannon 在 gh-101578 中贡献。)添加了
PyErr_DisplayException()
,它接受一个异常实例,用于取代旧式 APIPyErr_Display()
。 (由 Irit Katriel 在 gh-102755 中贡献。)PEP 683: 在 Python 中引入了永生对象,它允许对象绕过引用计数,并对 C-API 进行了相应修改:
_Py_IMMORTAL_REFCNT
: 定义对象的引用计数为永生对象。
_Py_IsImmortal
检测一个对象是否具有永生引用计数。PyObject_HEAD_INIT
这将把引用计数初始化为_Py_IMMORTAL_REFCNT
当配合Py_BUILD_CORE
使用时。
SSTATE_INTERNED_IMMORTAL
一个针对内部 unicode 对象的标识符为永生对象。
SSTATE_INTERNED_IMMORTAL_STATIC
一个针对内部 unicode为永生且静态的对象
sys.getunicodeinternedsize
这将返回总计的 unicode被管理的对象。 现在 refleak.py 需要这样才能正确地追踪引用计数和分配的块
(由 Eddie Elizondo 在 gh-84436 中贡献。)
PEP 684: 新增了
Py_NewInterpreterFromConfig()
函数和PyInterpreterConfig
,可用于创建具有单独 GIL 的子解释器。 (更多信息参见 PEP 684: 解释器级 GIL。) (由 Eric Snow 在 gh-104110 中贡献。)在 3.12 版的受限 C API 中,
Py_INCREF()
和Py_DECREF()
函数现在使用不透明函数调用的方式实现以隐藏实现细节。 (由 Victor Stinner 在 gh-105387 中贡献。)
移植到 Python 3.12¶
基于
Py_UNICODE*
表示形式的旧式 Unicode API 已被移除。 请迁移到基于 UTF-8 或wchar_t*
的 API。PyArg_ParseTuple()
等参数解析函数不再支持基于Py_UNICODE*
的格式(例如u
,Z
等)。 请迁移到其他 Unicode 格式如s
,z
,es
和U
。tp_weaklist
对于所有静态内置类型将始终为NULL
。 这是PyTypeObject
上的一个内部专属字段,但我们还是要指出这一变化以防有人碰巧仍然直接访问到该字段。 为避免出现中断,请考虑改用现有的公共 C-API,或在必要时使用(仅限内部使用的)宏_PyObject_GET_WEAKREFS_LISTPTR()
。现在这个内部专用的
PyTypeObject.tp_subclasses
可能不是一个有效的对象指针。 为了反映这一点我们将其类型改为 void*。 我们提到这一点是为了防止有人碰巧直接访问到这个内部专用字段。要获取子类的列表,请调用 Python 方法
__subclasses__()
(例如使用PyObject_CallMethod()
)。在
PyUnicode_FromFormat()
和PyUnicode_FromFormatV()
中添加对更多格式选项(左对齐、八进制、大写十六进制、intmax_t
、ptrdiff_t
、wchar_t
C 字符串、可变宽度和精度)的支持。 (由 Serhiy Storchaka 在 gh-98836 中贡献。)PyUnicode_FromFormat()
和PyUnicode_FromFormatV()
中未被识别的格式字符现在会设置一个SystemError
。 在之前的版本中它会导致格式字符串的所有其他部分被原样复制到结果字符串中,并丢弃任何额外的参数。 (由 Serhiy Storchaka 在 gh-95781 中贡献。)修复了
PyUnicode_FromFormat()
和PyUnicode_FromFormatV()
中错误的标志位置。 (由 Philip Georgi 在 gh-95504 中贡献。)希望添加
__dict__
或弱引用槽位的扩展类应分别使用Py_TPFLAGS_MANAGED_DICT
和Py_TPFLAGS_MANAGED_WEAKREF
来代替tp_dictoffset
和tp_weaklistoffset
。 目前仍支持使用tp_dictoffset
和tp_weaklistoffset
,但并不完全支持多重继承 (gh-95589),而且性能可能会变差。 声明了Py_TPFLAGS_MANAGED_DICT
的类应当调用_PyObject_VisitManagedDict()
和_PyObject_ClearManagedDict()
来遍历并清除它们的实例的字典。 要清除弱引用,请像之前一样调用PyObject_ClearWeakRefs()
。PyUnicode_FSDecoder()
函数不再接受类似字节串的路径,如bytearray
和memoryview
类型:只接受明确的bytes
类型字节字符串。 (由 Victor Stinner 在 gh-98393 中贡献。)Py_CLEAR
、Py_SETREF
和Py_XSETREF
宏现在只会对其参数求值一次。如果参数有附带影响,这些附带影响将不会再重复。 (由 Victor Stinner 在 gh-98724 中贡献。)解释器的错误指示器现在总是规范化的。 这意味着
PyErr_SetObject()
、PyErr_SetString()
以及其他设置错误指示器的函数在保存异常之前都会将其规范化。 (由 Mark Shannon 在 gh-101578 中贡献。)_Py_RefTotal
已不再具有重要性而保留它只是为了 ABI 的兼容性。 请注意,这是一个内部全局变量并且仅在调试版本中可用。 如果你碰巧要使用它那么你需要开始使用_Py_GetGlobalRefTotal()
。下面的函数将为新创建的类型选择一个合适的元类:
创建具有重载了
tp_new
的元类的类的做法已被弃用,在 Python 3.14+ 中将被禁止。 请注意这些函数会忽略元类的tp_new
,从而可能导致不完整的初始化。请注意
PyType_FromMetaclass()
(在 Python 3.12 中新增) 已禁止创建具有重载了tp_new
(在 Python 中为__new__()
) 的元类的类。由于
tp_new
重载了``PyType_From*`` 函数的几乎所有内容,因此两者互不兼容。 现有的行为 -- 在创建类型的一些步骤中忽略元类 -- 通常都是不安全的,因为(元)类会假定tp_new
已被调用。 目前还没有简单通用的绕过方式。 以下办法之一可能对你有用:如果你控制着元类,请避免在其中使用
tp_new
:如初始化可被跳过,则可以改在
tp_init
中完成。如果元类不需要从 Python 执行实例化,则使用
Py_TPFLAGS_DISALLOW_INSTANTIATION
旗标将其tp_new
设为NULL
。 这将使其可被PyType_From*
函数接受。
避免使用
PyType_From*
函数:如果不需要 C 专属的特性(槽位或设置实例大小),请通过 调用 元类来创建类型。如果你 知道 可以安全地跳过
tp_new
,就使用 Python 中的warnings.catch_warnings()
过滤掉弃用警告。
PyOS_InputHook
和PyOS_ReadlineFunctionPointer
将不再在 子解释器 中被调用。 这是因为客户端通常依赖进程级的全局状态(而这些回调没有办法恢复扩展模块状态)。这也避免了扩展程序在不支持(或尚未被加载)的子解释器中运行的情况。 请参阅 gh-104668 了解更多信息。
PyLongObject
对其内部字段进行了修改以提高性能。 虽然PyLongObject
的内部字段是私有的,但某些扩展模块会使用它们。 内部字段不应再被直接访问,而应改用以PyLong_...
打头的 API 函数。 新增了两个 暂定 API 函数用于高效访问适配至单个机器字的PyLongObject
的值:通过
PyMem_SetAllocator()
设置的自定义分配器现在必须是线程安全的,无论内存域是什么。 没有自己的状态的分配器,包括“钩子”将不会受影响。 如果你的自定义分配器还不是线程安全的且你需要指导则请创建一个新的 GitHub 问题并抄送给@ericsnowcurrently
。
弃用¶
已弃用的全局配置变量:
Py_HashRandomizationFlag
: 使用PyConfig.use_hash_seed
和PyConfig.hash_seed
Py_LegacyWindowsFSEncodingFlag
: 使用PyPreConfig.legacy_windows_fs_encoding
Py_FileSystemDefaultEncoding
: 使用PyConfig.filesystem_encoding
Py_HasFileSystemDefaultEncoding
: 使用PyConfig.filesystem_encoding
Py_FileSystemDefaultEncodeErrors
: 使用PyConfig.filesystem_errors
Py_UTF8Mode
: 使用PyPreConfig.utf8_mode
(参见Py_PreInitialize()
)
Py_InitializeFromConfig()
API 应当改为使用PyConfig
。 (由 Victor Stinner 在 gh-77782 中贡献。)使用可变基类创建不可变类型 (
Py_TPFLAGS_IMMUTABLETYPE
) 的做法已被弃用并将在 Python 3.14 中禁用。structmember.h
头文件已被弃用,不过它仍可继续使用也没有计划将其移除。现在只需包括
Python.h
即可获得其内容,如果找不到请添加Py
前缀:类型宏如
Py_T_INT
,Py_T_DOUBLE
等(之前为T_INT
,T_DOUBLE
等)旗标
Py_READONLY
(之前为READONLY
) 和Py_AUDIT_READ
(之前为全大写形式)
部分条目未从
Python.h
对外公开:T_OBJECT
(使用Py_T_OBJECT_EX
)T_NONE
(之前未写入文档,并且相当怪异)不进行任何操作的宏
WRITE_RESTRICTED
。RESTRICTED
和READ_RESTRICTED
宏,等同于Py_AUDIT_READ
。在某些配置中,
Python.h
未被<stddef.h>
包括。 在使用offsetof()
时应当手动包括它。
已被弃用的头文件将继续以原来的名称提供原来的内容。 你的旧代码可以保持不变,除非额外的包括指令和无命名空间宏会给你带来很大困扰。
(由 Petr Viktorin 在 gh-47146 中贡献,基于 Alexander Belopolsky 和 Matthias Braun 在先前的工作。).)
PyErr_Fetch()
和PyErr_Restore()
已被弃用。请使用PyErr_GetRaisedException()
和PyErr_SetRaisedException()
代替。(由 Mark Shannon 在:gh:101578 贡献)。PyErr_Display()
已被弃用,请改用PyErr_DisplayException()
。 (由 Irit Katriel 在 gh-102755 中贡献。)_PyErr_ChainExceptions
已被弃用。 请改用_PyErr_ChainExceptions1
。 (由 Irit Katriel 在 gh-102192 中贡献。)使用
PyType_FromSpec()
,PyType_FromSpecWithBases()
或PyType_FromModuleAndSpec()
来创建所属元类重载了tp_new
的类的做法已被弃用。 请改为调用相应元类。is deprecated. Call the metaclass instead.
移除¶
移除了
token.h
头文件。 从来就没有任何公用的分词器 C API。token.h
头文件只是为 Python 内部使用而设计的。 (由 Victor Stinner 在 gh-92651 中贡献。)旧式 Unicode API 已被移除。 请参阅 PEP 623 了解详情。for detail.
PyUnicode_WCHAR_KIND
PyUnicode_AS_UNICODE()
PyUnicode_AsUnicode()
PyUnicode_AsUnicodeAndSize()
PyUnicode_AS_DATA()
PyUnicode_FromUnicode()
PyUnicode_GET_SIZE()
PyUnicode_GetSize()
PyUnicode_GET_DATA_SIZE()
移除了
PyUnicode_InternImmortal()
函数宏。 (由 Victor Stinner 在 gh-85858 中贡献。).)从多个标准库模块和测试中移除了
Jython
兼容性处理。 (由 Nikita Sobolev 在 gh-99482 中贡献。)从
ctypes
模块移除了_use_broken_old_ctypes_structure_semantics_
旗标。 (由 Nikita Sobolev 在 gh-99285 中贡献。)