Python 3.12 有什么新变化
Python 3.12 有什么新变化
编者:
Adam Turner
本文介绍 Python 3.12 相比 3.11 增加的新特性。 Python 3.12 已于 2023 年 10 月 2 日发布。 要获取详细信息,可参阅 changelog。
参见
PEP 693 — Python 3.12 发布计划
摘要 — 发布重点
Python 3.12 是 Python 编程语言的一个稳定发布版,包含一系列对语言和标准库的改变。 库的改变主要集中在清理已弃用的 API、易用性和正确性等方面。 值得注意的是,distutils 包已从标准库中移除。 os 和 pathlib 中的文件系统支持得到了许多改进,一些模块的性能也得到了提升。
语言的改变主要集中在可用性方面,如 f-字符串 的许多限制已被移除,而 ‘Did you mean …’ 提示消息继续得到改进。 新的 类型形参语法 和 type 语句提升了 泛型类型 和 类型别名 配合静态类型检查器使用时的效率。
本文并不试图提供所有新功能的完整规范说明,而是提供一个方便的概览。 如需了解完整细节,请参阅相应文档,如 标准库参考 和 语言参考。 如果你想了解某项改变的完整实现和设计理念,请参阅相应新特性的 PEP;但请注意一旦某项特性已完全实现则相应 PEP 通常不会再继续更新。
新的语法特性:
- PEP 695,类型形参语法和 type 语句
新的语法特性:
- PEP 701,f-字符串 语法的改进
解释器的改进:
-
PEP 684,单独的每解释器 GIL
-
PEP 669,低开销的监控
-
针对 NameError, ImportError 和 SyntaxError 异常 改进了 ‘Did you mean …’ 提示消息。
对 Python 数据模型的改进:
- PEP 688,使用 Python 的 缓冲区协议
标准库中的重大改进:
-
pathlib.Path 类现在支持子类化
-
os 模块获得了多项针对 Windows 支持的改进
-
基于 运行时可检测协议 的 isinstance() 检测获得了 2 至 20 倍的提速
-
asyncio 包的性能获得了多项改进,一些基准测试显示有 75% 的提速。
-
由于 PEP 701 中的更改,通过 tokenize 模块生成令牌(token)的速度最多可提高 64%。
安全改进:
- 用来自 HACL* 项目的经过正式验证的代码替代 SHA1, SHA3, SHA2-384, SHA2-512 和 MD5 的内置 hashlib 实现。 这些内置实现保留作为仅在当 OpenSSL 未提供它们时使用的回退选项。
C API 的改进:
-
PEP 697,不稳定 C API 层
-
PEP 683,永生对象
CPython 实现的改进:
-
PEP 709,推导式内联化
-
对 Linux
perf性能分析器的 CPython 支持 -
在受支持的平台上实现栈溢出保护
新的类型标注特性:
-
PEP 698,typing.override() 装饰器
重要的弃用、移除或限制:
-
PEP 623: 在 Python 的 C API 中移除 Unicode 对象中的
wstr,使每个 str 对象的大小缩减至少 8 个字节。 -
PEP 632: 移除
distutils包。 请参阅 迁移指南 了解有关替换其所提供的 API 的建议。 第三方 Setuptools 包将继续提供distutils,如果你在 Python 3.12 及更高版本中仍然需要它的话。 -
gh-95299: 不在使用 venv 创建的虚拟环境中预装
setuptools。 这意味着distutils、setuptools、pkg_resources和easy_install默认将不再可用;要访问这些工具请在 激活的 虚拟环境中运行pip install setuptools。 -
移除了
asynchat、asyncore和imp模块,以及一些 unittest.TestCase 方法别名。
新的特性
PEP 695: 类型形参语法
PEP 484 下的泛型类和函数是使用详细语法声明的,这使得类型参数的范围不明确,并且需要显式声明变化。
PEP 695 引入了一种新的、更紧凑、更明确的方式来创建 泛型类 和 函数:
def max[T](args: Iterable[T]) -> T:
...
class list[T]:
def __getitem__(self, index: int, /) -> T:
...
def append(self, element: T) -> None:
...
此外,该 PEP 引入了一种新的方法来使用 type 语句声明 类型别名,该语句会创建 TypeAliasType 的实例:
type Point = tuple[float, float]
类型别名也可以是 generic:
type Point[T] = tuple[T, T]
新语法允许声明 TypeVarTuple 和 ParamSpec 形参,以及带边界或约束的 TypeVar 形参:
type IntFunc[**P] = Callable[P, int] # ParamSpec
type LabeledTuple[*Ts] = tuple[str, *Ts] # TypeVarTuple
type HashableSequence[T: Hashable] = Sequence[T] # 带边界的 TypeVar
type IntOrStrSequence[T: (int, str)] = Sequence[T] # 带约束的 TypeVar
类型别名的值以及通过此语法创建的类型变量的边界和约束仅在需要时才进行求值 (参见 惰性求值)。 这意味着类型别名可以引用稍后在文件中定义的其他类型。
通过类型参数列表声明的类型参数在声明的作用域和任何嵌套的作用域内都可见,但在外部作用域内不可见。 例如,它们可以用于泛型类的方法的类型注解或类体中。 但是,在定义类之后,不能在模块范围中使用它们。 有关类型参数的运行时语义的详细描述,请参见 类型形参列表。
为了支持这些作用域定义,引入了一种新的作用域,即 标注作用域。 标注作用域的行为在很大程度上类似于函数作用域,但与封闭类作用作用域的交互方式不同。 在 Python 3.13 中,标注 也将在标注作用域中进行求值。
更多细节请参见 PEP 695。
(PEP由 Eric Traut 撰写。 由 Jelle Zijlstra、Eric Traut 和其他人在 gh-103764 中实现。)
PEP 701:f-字符串的句法形式化
PEP 701 取消了对 f-字符串 使用的一些限制。 f-字符串内部的表达式部分现在可以是任何有效的 Python 表达式,包括重用了与标记 f-字符串本身相同的引号的字符串、多行表达式、注释、反斜杠以及 unicode 转义序列。 让我们详细介绍一下:
- 引号重用:在 Python 3.11 中,重用与标记 f-字符串本身相同的引号会引发 SyntaxError,迫使用户使用其他可用的引号(如在 f-字符串使用单引号时使用双引号或三重引号)。 在 Python 3.12 中,你现在可以这样做了:
>>> 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'
- 多行表达式和注释:在 Python 3.11 中,f-字符串表达式必须在一行中完成定义,即使 f-字符串中的表达式在正常情况下可以跨多行(如在多行中定义的列表字面值),这使得它们更难被读懂。 在 Python 3.12 中,你现在可以定义跨越多行的 f-字符串并添加内联注释:
>>> 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'
- 反斜杠和 unicode 字符:在 Python 3.12 之前,f-字符串表达式不能包含任何
\字符。 这也影响了 unicode 转义序列 (如\N{snowman}),因为这些序列包含\N部分,而这部分以前不能作为 f-字符串表达式组件的一部分。 现在,你可以这样定义表达式:
>>> 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。
实现此特性的一个正面的附带影响是(通过使用 PEG 解析器 来解析 f-字符串),现在 f-字符串的错误消息会更加精确,包括错误的确切位置。例如,在 Python 3.11 中,下面的 f-字符串将引发一个 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 684: 每解释器 GIL
PEP 684 引入了每解释器 GIL,使得现在可以创建带有单独的每解释器 GIL 的子解释器。 这将允许 Python 程序充分利用多个 CPU 核心。 此特性目前仅能通过 C-API 使用,不过相应的 Python API 预计将在 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;
}
/* 新解释器现已在当前线程中激活。 */
有关如何将For further examples how to use the C-API 用于具有每解释器 GIL 的子解释器的更多示例,请参见 Modules/_xxsubinterpretersmodule.c。
(由 Eric Snow 在 gh-104210 等中贡献。)
PEP 669:针对 CPython 的低影响监控
PEP 669 定义了一个新的 API 用于性能分析器、调试器和其他在 CPython 中监控事件的工具。 它覆盖了大范围的事件,包括调用、返回、行、异常、跳转等等。 这意味着你将只为你所使用的东西付出开销,提供了对近乎零开销的调试器和覆盖工具的支持。 请参阅 sys.monitoring 了解详情。
(由 Mark Shannon 在 gh-103082 中贡献。)
PEP 688: 使缓冲区协议在Python中可访问
PEP 688 引入了一种在 Python 代码中使用 缓冲区协议 的方法。实现 buffer() 方法的类现在可以作为缓冲区类型使用。
新的 collections.abc.Buffer ABC(抽象基类)提供了一种表示缓冲区对象的标准方法,例如在类型注释中。 新的 inspect.BufferFlags 枚举表示可用于自定义缓冲区创建的标志。 (由 Jelle Zijlstra 在 gh-102500 中贡献。)
PEP 709:推导式内联
字典、列表和集合推导式现在都是内联的,而不是为每次执行推导式都创建一个新的一次性函数对象。 这样可以将推导式的执行速度提高最多两倍。 更多细节请参阅 PEP 709。
推导式迭代变量将保持隔离而不会覆盖外作用域中的同名变量,在离开推导式后也不再可见。 内联确实会导致一些可见的行为变化:
-
回溯中的推导式不再有单独的帧,跟踪/评测也不再将推导式显示为函数调用。
-
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]。
(由 Carl Meyer 和 Vladimir Matveev 在 PEP 709 中贡献。)
改进的错误消息
>>> 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'?
- 改进针对实例的 NameError 异常的错误建议。 现在如果在方法中引发了 NameError 而实例具有与异常中的名称完全相同的属性,建议将会包括
self.<NAME>而不是方法作用域中最接近的匹配项。 (由 Pablo Galindo 在 gh-99139 中贡献。)
>>> class A:
... def __init__(self):
... self.blech = 1
...
... def foo(self):
... somethin = blech
...
>>> A().foo()
Traceback (most recent call last):
File "<stdin>", line 1
somethin = blech
^^^^^
NameError: name 'blech' is not defined. Did you mean: 'self.blech'?
- 改进了当用户输入
import x from y而不是from y import x时产生的 SyntaxError 错误消息。 (由 Pablo Galindo 在 gh-98931 中贡献。)
>>> import a.y.z from b.y.z
Traceback (most recent call last):
File "<stdin>", line 1
import a.y.z from b.y.z
^^^^^^^^^^^^^^^^^^^^^^^
SyntaxError: Did you mean to use 'from ... import ...' instead?
- 由失败的
from <module> import <name>语句引发的 ImportError 异常现在会包括根据<module>中的可用名称对<name>的值提出的建议。 (由 Pablo Galindo 在 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'?
有关类型提示的新增特性
本节介绍了影响 类型提示 和 typing 模块的主要更改。
PEP 692: 使用 TypedDict 进行更精确的 **kwargs 类型标注
在函数签名中的 **kwargs 类型标注(由 PEP 484 引入)只允许在所有 **kwargs 都属于同一类型的情况下进行有效标注。
PEP 692 通过依赖类型化的字典规定了一种更精确的针对 **kwargs 的类型标注方式:
from typing import TypedDict, Unpack
class Movie(TypedDict):
name: str
year: int
def foo(**kwargs: Unpack[Movie]): ...
更多细节请参见 PEP 692。
(由 Franek Magiera 在 gh-103629 中贡献。)
PEP 698:覆盖静态类型的装饰器
一个新的装饰器 typing.override() 已添加到 typing 模块中。 它向类型检查器指示该方法旨在重写超类中的方法。 这允许类型检查器在打算重写基类中的某个方法实际上没有重写的情况下捕获错误。
示例:
from typing import override
class Base:
def get_color(self) -> str:
return "blue"
class GoodChild(Base):
@override # 正确:重写 Base.get_color
def get_color(self) -> str:
return "yellow"
class BadChild(Base):
@override # 类型检查错误:不能重写 Base.get_color
def get_colour(self) -> str:
return "red"
更多细节参见 PEP 698。
(由 Steven Troxler 在 gh-101561 中贡献。)
其他语言特性修改
-
解析器现在在解析包含空字节的源代码时引发 SyntaxError。 (由 Pablo Galindo 在 gh-96670 中贡献 。)
-
不是有效转义序列的反斜杠加字符组合现在会生成 SyntaxWarning,而不是 DeprecationWarning。 例如,
re.compile("\d+\.\d+")现在会发出 SyntaxWarning ("\d"是一个无效的转义序列,请使用原始字符串来表示正则表达式:re.compile(r"\d+\.\d+"))。 在未来的 Python 版本中,最终将引发 SyntaxError,而不是 SyntaxWarning。 (由 Victor Stinner 在 gh-98401 中贡献。) -
值大于
0o377(例如:"\477") 的八进制转义序列,在 Python 3.11 中已弃用,现在会产生 SyntaxWarning,而不是 DeprecationWarning。 在未来的 Python 版本中,它们最终将是 SyntaxError。 (由 Victor Stinner 在 gh-98401 中贡献。) -
未存储在推导式目标部分中的变量现在可以在赋值表达式 (
:=) 中使用。 例如,在[(b := 1) for a, b.prop in some_iter]中,现在允许对b进行赋值。 请注意,根据 PEP 572,仍然不允许向存储在推导式目标部分中的变量 (如a) 赋值。 (由 Nikita Sobolev 在 gh-100581 中贡献。) -
在类或类型对象的
__set_name__方法中引发的异常不再由 RuntimeError 来包装。 上下文信息将作为 PEP 678 注释添加到异常中。 (由 Irit Katriel 在 gh-77757 中贡献。) -
当
try-except*构造处理整个 ExceptionGroup 并引发另一个异常时,该异常不再封装在 ExceptionGroup 中。 在 3.11.4 版中也进行了更改。 (由 Irit Katriel 在 gh-103590 中贡献。) -
垃圾回收器现在只在 Python 字节码评估循环的 eval-breaker 机制上运行,而不是在对象分配上运行。 垃圾回收也可以在调用 PyErr_CheckSignals() 时运行,因此需要长时间运行而不执行任何 Python 代码的 C 扩展也有机会定期执行垃圾回收。 (由 Pablo Galindo 在 gh-97922 中贡献。)
-
所有期望布尔参数的内置和扩展可调用函数现在都接受任何类型的参数,而不仅仅是 bool 和 int。 (由 Serhiy Storchaka 在 gh-60203 中贡献。)
-
memoryview 现在支持半精度浮点类型(”e” 格式代码)。 (由 Donghee Na 和 Antoine Pitrou 在 gh-90751 中贡献。)
-
slice 对象现在是可哈希的,允许它们用作字典的键和集合项。 (由 Will Bradshaw、Furkan Onder 和 Raymond Hettinger 在 gh-101264 中贡献。)
-
sum() 现在使用 Neumaier 求和算法以改善对浮点数或混合了整数和浮点数时求和运算的准确性和可换算性。 (由 Raymond Hettinger 在 gh-100425 中贡献。)
-
ast.parse() 现在会在解析包含空字节的源代码时引发 SyntaxError 而不是 ValueError。 (由 Pablo Galindo 在 gh-96670 中贡献 。)
-
tarfile 中的提取方法和 shutil.unpack_archive() 有一个新的 filter 参数,它允许限制可能令人惊讶或危险的 tar 功能,例如在目标目录之外创建文件。 相关细节请参阅 tarfile 提取过滤器。 在 Python 3.14 中。默认值将切换为
'data'。 (由 Petr Viktorin 在 PEP 706 中贡献。) -
如果底层映射是可哈希的,那么 types.MappingProxyType 实例现在是可哈希的。 (由 Serhiy Storchaka 在 gh-87995 中贡献。)
-
通过新的环境变量 PYTHONPERFSUPPORT 和命令行选项 -X perf 以及新的 sys.activate_stack_trampoline(), sys.deactivate_stack_trampoline() 和 sys.is_stack_trampoline_active() 函数添加了对 perf 性能分析器的支持。 (由 Pablo Galindo 设计。 由 Pablo Galindo 和 Christian Heimes 在 gh-96123 中贡献并包含来自 Gregory P. Smith [Google] 和 Mark Shannon 的帮助。)
新增模块
- 无。
改进的模块
array
- array.array 类现在支持下标,使其成为 generic type。 (由 Jelle Zijlstra 在 gh-98658 中贡献。)
asyncio
-
在 asyncio 中写入套接字的性能得到了显著提高。
asyncio现在可以避免在写入套接字时进行不必要的复制,并在平台支持的情况下使用 sendmsg()。 (由 Kumar Aditya 在 gh-91166 中贡献。) -
添加了 asyncio.eager_task_factory() 和 asyncio.create_eager_task_factory() 函数以允许在主动型任务执行中选择事件循环,使某些用例的速度提升了 2 至 5 倍。 (由 Jacob Bower 和 Itamar Oren 在 gh-102853, gh-104140 和 gh-104138 中贡献。)
-
在 Linux 上,如果 os.pidfd_open() 可用且能工作则 asyncio 默认会使用 asyncio.PidfdChildWatcher 而不是 asyncio.ThreadedChildWatcher。 (由 Kumar Aditya 在 gh-98024 中贡献。)
-
现在事件循环会针对每个平台使用最佳的可用子监视器 (在受支持的情况下使用 asyncio.PidfdChildWatcher,否则使用 asyncio.ThreadedChildWatcher),因此不建议手动配置子监视器。 (由 Kumar Aditya 在 gh-94597 中贡献。)
-
为 asyncio.run() 添加了形参 loop_factory ,以允许指定自定义事件循环工厂。 (由 Kumar Aditya 在 gh-99388 中贡献。)
-
添加了 asyncio.current_task() 的 C 实现以实现 4 - 6 倍的加速。 (由 Itamar Oren 和 Pranav Thulasiram Bhat 在 gh-100344 中贡献。)
-
asyncio.iscoroutine() 现在为生成器返回
False,因为 asyncio 不支持传统的基于生成器的协程。 (由 Kumar Aditya 在 gh-102748 中贡献。) -
asyncio.wait() 和 asyncio.as_completed() 现在接受生成器 yield 任务。 (由 Kumar Aditya 在 gh-78530 中贡献。)
calendar
- 添加了枚举 calendar.Month 和 calendar.Day 来定义年份中的每一月和星期中的每一日。 (由 Prince Roshan 在 gh-103636 中贡献。)
csv
- 增加了 csv.QUOTE_NOTNULL 和 csv.QUOTE_STRINGS 旗标以通过 reader 和 writer 对象来提供对
None和空字符串更细粒度的控制。
dis
-
伪指令操作码(由编译器使用但不会出现在可执行字节码中)现在将暴露在 dis 模块中。 HAVE_ARGUMENT 仍然与实际的操作码相关,但对伪指令来说没有用处。 请改用新的 dis.hasarg 多项集。 (由 Irit Katriel 在 gh-94216 中贡献。)
-
添加了 dis.hasexc 多项集来表示设置异常处理器的指令。 (由 Irit Katriel 在 gh-94216 中贡献。)
fractions
- 类型为 fractions.Fraction 的对象现在支持浮点格式。 (由 Mark Dickinson 在 gh-100161 中贡献。)
importlib.resources
-
importlib.resources.as_file() 现在将支持资源目录。 (由 Jason R. Coombs 在 gh-97930 中贡献。)
-
将 importlib.resources.files() 的第一个形参重命名为 anchor 。 (由 Jason R. Coombs 在 gh-100598 中贡献。)
inspect
-
增加了 inspect.markcoroutinefunction() 来标记返回 coroutine 的同步函数以便与 inspect.iscoroutinefunction() 一起使用。 (由 Carlton Gibson 在 gh-99247 中贡献。)
-
添加 inspect.getasyncgenstate() 和 inspect.getasyncgenlocals() 用来确定异步发生器的当前状态。 (由 Thomas Krennwallner 在 gh-79940 中贡献。)
-
inspect.getattr_static() 的性能已得到显著提升。 对该函数的大多数调用相比 Python 3.11 至少应有 2 倍的加速。 (由 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
-
增加对子类化 pathlib.PurePath 和 pathlib.Path,加上它们的 Posix 和 Windows 专属变体形式的支持。 子类可以重载 pathlib.PurePath.with_segments() 方法来在路径实例之间传递信息。
-
添加 pathlib.Path.walk() 用于遍历目录树并生成其中的所有文件或目录名,类似于 os.walk()。 (由 Stanislav Zmiev 在 gh-90385 中贡献。)
-
在 pathlib.PurePath.relative_to() 中添加了 walk_up 可选形参以允许在结果中插入
..条目;此行为与 os.path.relpath() 更为一致。(由 Domenico Ragusa 在 gh-84538 中贡献。) -
添加 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() 中添加默认值
lambd=1.0。 (由 Raymond Hettinger 在 gh-100234 中贡献。)
shutil
-
shutil.make_archive() 现在将 rootdir 参数传递给支持它的自定义存档程序。 在这种情况下,它不再临时将进程的当前工作目录更改为 rootdir 来执行存档。 (由 Serhiy Storchaka 在 gh-74696 中贡献。)
-
shutil.rmtree() 现在接受一个新的参数 onexc ,它是一个类似 onerror 的错误处理器,但它接受一个异常实例而不是一个 (typ, val, tb) 三元组。 onerror 已被弃用。 (由 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
-
向 sqlite3.Connection 添加 sqlite3.Connection.autocommit 属性并向 sqlite3.connect() 添加 autocommit 形参用于控制兼容 PEP 249 的 事务处理。 (由 Erlend E. Aasland 在 gh-83638 中贡献。)
-
向 sqlite3.Connection.load_extension() 添加 entrypoint 仅限关键字形参,用于覆盖 SQLite 扩展入口点。 (由 Erlend E. Aasland 在 gh-103015 中贡献。)
-
向 sqlite3.Connection 添加 sqlite3.Connection.getconfig() 和 sqlite3.Connection.setconfig() 用于对数据库连接进行配置修改。 (由 Erlend E. Aasland 在 gh-103489 中贡献。)
statistics
- 扩展 statistics.correlation() 以
ranked方法的形式包括对分级数据的斯皮尔曼相关性计算。 (由 Raymond Hettinger 在 gh-95861 中贡献。)
sys
-
添加了 sys.monitoring 命名空间以公开新的 PEP 669 监控 API。 (由 Mark Shannon 在 gh-103082 中贡献。)
-
增加了 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
- tokenize 模块包括了 PEP 701 所引入的更改。 (由 Marta Gómez Macías 和 Pablo Galindo 在 gh-102856 中贡献。) 请参阅 移植到 Python 3.12 了解有关对 tokenize 模块的更改详情。
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) # 无变化,虽然 HasX 现在也有一个 "y" 属性
True
应用这项改变是为了提高针对运行时可检测协议的 isinstance() 检测速度。
-
针对 运行时可检测协议 的 isinstance() 检测的性能表现有显著的改进。 对于仅有少量成员的协议的大部分
isinstance()检测相比 3.11 应当至少有 2 倍的加速。 不过,对于具有大量成员的协议的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 在 gh-48330 中贡献。)
uuid
(本文超出站点单文档体积上限,已按小节截断)
