Python 3.10 的新特性 — Python 文档
Python 3.10 中的新功能
- 释放
- 日期
- November 21, 2021
- 编辑
- 巴勃罗·加林多·萨尔加多
本文解释了 Python 3.10 中与 3.9 相比的新特性。
有关完整详细信息,请参阅 变更日志 。
摘要 – 发布亮点
新的语法特性:
- PEP 634,结构模式匹配:规范
- PEP 635,结构模式匹配:动机和基本原理
- PEP 636,结构模式匹配:教程
- :issue:`12782`,现在正式允许带括号的上下文管理器。
标准库中的新功能:
- PEP 618,添加可选长度检查到 zip。
解释器改进:
- PEP 626,用于调试和其他工具的精确行号。
新的打字功能:
重要的弃用、删除或限制:
- PEP 644,需要 OpenSSL 1.1.1 或更新版本
- PEP 632,弃用 distutils 模块。
- PEP 623,弃用并准备移除 PyUnicodeObject 中的 wstr 成员。
- PEP 624,删除 Py_UNICODE 编码器 API
- PEP 597,添加可选编码警告
新功能
带括号的上下文管理器
现在支持使用括号在上下文管理器中跨多行继续。 这允许以类似于以前使用 import 语句可能的方式在多行中格式化一长串上下文管理器。 例如,所有这些示例现在都有效:
with (CtxManager() as example):
...
with (
CtxManager1(),
CtxManager2()
):
...
with (CtxManager1() as example,
CtxManager2()):
...
with (CtxManager1(),
CtxManager2() as example):
...
with (
CtxManager1() as example1,
CtxManager2() as example2
):
...
也可以在封闭组的末尾使用尾随逗号:
with (
CtxManager1() as example1,
CtxManager2() as example2,
CtxManager3() as example3,
):
...
这种新语法使用了新解析器的非 LL(1) 能力。 查看 PEP 617 了解更多详情。
(由 Guido van Rossum、Pablo Galindo 和 Lysandros Nikolaou 在 :issue:`12782` 和 :issue:`40334` 中提供。)
更好的错误信息
语法错误
当解析包含未闭合括号或括号的代码时,解释器现在包括括号未闭合括号的位置,而不是显示 SyntaxError:解析 时出现意外 EOF 或指向某些不正确的位置。 例如,考虑以下代码(注意未闭合的“{”):
expected = {9: 1, 18: 2, 19: 2, 27: 3, 28: 3, 29: 3, 36: 4, 37: 4,
38: 4, 39: 4, 45: 5, 46: 5, 47: 5, 48: 5, 49: 5, 54: 6,
some_other_code = foo()
先前版本的解释器将令人困惑的地方报告为语法错误的位置:
File "example.py", line 3
some_other_code = foo()
^
SyntaxError: invalid syntax
但在 Python 3.10 中,会发出更多信息错误:
File "example.py", line 1
expected = {9: 1, 18: 2, 19: 2, 27: 3, 28: 3, 29: 3, 36: 4, 37: 4,
^
SyntaxError: '{' was never closed
以类似的方式,涉及未闭合字符串文字(单引号和三引号)的错误现在指向字符串的开头,而不是报告 EOF/EOL。
这些改进的灵感来自 PyPy 解释器之前的工作。
(由 Pablo Galindo 在 :issue:`42864` 和 Batuhan Taskaya 在 :issue:`40176` 中贡献。)
SyntaxError 解释器引发的异常现在将突出显示构成语法错误本身的表达式的完整错误范围,而不仅仅是检测到问题的位置。 这样,而不是显示(在 Python 3.10 之前):
>>> foo(x, z for z in range(10), t, w)
File "<stdin>", line 1
foo(x, z for z in range(10), t, w)
^
SyntaxError: Generator expression must be parenthesized
现在 Python 3.10 将异常显示为:
>>> foo(x, z for z in range(10), t, w)
File "<stdin>", line 1
foo(x, z for z in range(10), t, w)
^^^^^^^^^^^^^^^^^^^^
SyntaxError: Generator expression must be parenthesized
此改进由 Pablo Galindo 在 :issue:`43914` 中贡献。
SyntaxError 异常的大量新的专门消息已被合并。 一些最显着的如下:
块前缺少
:
:>>> if rocket.position > event_horizon File "<stdin>", line 1 if rocket.position > event_horizon ^ SyntaxError: expected ':'
(由 Pablo Galindo 在 中提供:issue:`42997`)
理解目标中的无括号元组:
>>> {x,y for x,y in zip('abcd', '1234')} File "<stdin>", line 1 {x,y for x,y in zip('abcd', '1234')} ^ SyntaxError: did you forget parentheses around the comprehension target?
(由 Pablo Galindo 在 中提供:issue:`43017`)
集合文字中和表达式之间缺少逗号:
>>> items = { ... x: 1, ... y: 2 ... z: 3, File "<stdin>", line 3 y: 2 ^ SyntaxError: invalid syntax. Perhaps you forgot a comma?
(由 Pablo Galindo 在 中提供:issue:`43822`)
不带括号的多种异常类型:
>>> try: ... build_dyson_sphere() ... except NotEnoughScienceError, NotEnoughResourcesError: File "<stdin>", line 3 except NotEnoughScienceError, NotEnoughResourcesError: ^ SyntaxError: multiple exception types must be parenthesized
(由 Pablo Galindo 在 中提供:issue:`43149`)
缺少
:
和字典文字中的值:>>> values = { ... x: 1, ... y: 2, ... z: ... } File "<stdin>", line 4 z: ^ SyntaxError: expression expected after dictionary key and ':' >>> values = {x:1, y:2, z w:3} File "<stdin>", line 1 values = {x:1, y:2, z w:3} ^ SyntaxError: ':' expected after dictionary key
(由 Pablo Galindo 在 中提供:issue:`43823`)
try
块没有except
或finally
块:>>> try: ... x = 2 ... something = 3 File "<stdin>", line 3 something = 3 ^^^^^^^^^ SyntaxError: expected 'except' or 'finally' block
(由 Pablo Galindo 在 中提供:issue:`44305`)
在比较中使用
=
代替==
:>>> if rocket.position = event_horizon: File "<stdin>", line 1 if rocket.position = event_horizon: ^ SyntaxError: cannot assign to attribute here. Maybe you meant '==' instead of '='?
(由 Pablo Galindo 在 中提供:issue:`43797`)
*
在 f 弦中的用法:>>> f"Black holes {*all_black_holes} and revelations" File "<stdin>", line 1 (*all_black_holes) ^ SyntaxError: f-string: cannot use starred expression here
(由 Pablo Galindo 在 中提供:issue:`41064`)
缩进错误
许多 IndentationError 异常现在有更多关于期望缩进的块类型的上下文,包括语句的位置:
>>> def foo():
... if lel:
... x = 2
File "<stdin>", line 3
x = 2
^
IndentationError: expected an indented block after 'if' statement in line 2
属性错误
打印 AttributeError 时,PyErr_Display()
将提供引发异常的对象中类似属性名称的建议:
>>> collections.namedtoplo
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: module 'collections' has no attribute 'namedtoplo'. Did you mean: namedtuple?
(由 Pablo Galindo 在 中提供:issue:`38530`。)
警告
请注意,如果未调用
PyErr_Display()
来显示错误,则这将不起作用,如果使用其他自定义错误显示函数,则可能会发生这种错误。 这是一些 REPL 中常见的场景,比如 IPython。
名称错误
当打印由解释器引发的 NameError 时,PyErr_Display()
将在引发异常的函数中提供类似变量名称的建议:
>>> schwarzschild_black_hole = None
>>> schwarschild_black_hole
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'schwarschild_black_hole' is not defined. Did you mean: schwarzschild_black_hole?
(由 Pablo Galindo 在 中提供:issue:`38530`。)
警告
请注意,如果未调用
PyErr_Display()
来显示错误,这将不起作用,如果使用其他一些自定义错误显示函数,则会发生这种情况。 这是一些 REPL 中常见的场景,比如 IPython。
PEP 626:用于调试和其他工具的精确行号
PEP 626 为调试、分析和覆盖工具带来了更精确和可靠的行号。 为所有执行的代码行和仅为执行的代码行生成具有正确行号的跟踪事件。
框架对象的 f_lineno
属性将始终包含预期的行号。
代码对象的 co_lnotab
属性已被弃用,将在 3.12 中移除。 需要从偏移量转换为行号的代码应改用新的 co_lines()
方法。
PEP 634:结构模式匹配
结构模式匹配已以 匹配语句 和 case 语句 模式的关联动作的形式添加。 模式由序列、映射、原始数据类型以及类实例组成。 模式匹配使程序能够从复杂的数据类型中提取信息,在数据结构上进行分支,并根据不同形式的数据应用特定的操作。
语法和操作
模式匹配的通用语法是:
match subject:
case <pattern_1>:
<action_1>
case <pattern_2>:
<action_2>
case <pattern_3>:
<action_3>
case _:
<action_wildcard>
match 语句采用表达式并将其值与作为一个或多个 case 块给出的连续模式进行比较。 具体来说,模式匹配通过以下方式运作:
- 使用具有类型和形状的数据(
subject
)- 评估
match
语句中的subject
- 从上到下将主题与
case
语句中的每个模式进行比较,直到确认匹配。- 执行与确认匹配的模式相关联的操作
- 如果没有确认完全匹配,最后一种情况,通配符
_
(如果提供)将用作匹配情况。 如果未确认完全匹配且不存在通配符大小写,则整个匹配块为空操作。
声明式方法
读者可能会通过使用 C、Java 或 JavaScript(以及许多其他语言)中的 switch 语句将主题(数据对象)与文字(模式)进行匹配的简单示例来了解模式匹配。 switch 语句通常用于将对象/表达式与包含文字的 case 语句进行比较。
在 Scala 和 Elixir 等语言中可以找到更强大的模式匹配示例。 对于结构模式匹配,该方法是“声明性的”并明确说明数据匹配的条件(模式)。
虽然使用嵌套“if”语句的“命令式”系列指令可用于完成类似于结构模式匹配的事情,但不如“声明式”方法清晰。 相反,“声明式”方法声明了匹配要满足的条件,并且通过其显式模式更具可读性。 虽然结构模式匹配可以以其最简单的形式使用,将变量与 case 语句中的文字进行比较,但它对 Python 的真正价值在于它对主题类型和形状的处理。
简单模式:匹配文字
让我们将此示例视为最简单形式的模式匹配:一个值,即主题,与多个文字匹配,即模式。 在下面的示例中,status
是匹配语句的主题。 模式是每个 case 语句,其中文字表示请求状态代码。 匹配后执行与案例相关的操作:
def http_error(status):
match status:
case 400:
return "Bad request"
case 404:
return "Not found"
case 418:
return "I'm a teapot"
case _:
return "Something's wrong with the internet"
如果上述函数传递了 418 的 status
,则返回“我是茶壶”。 如果上述函数传递了 500 的 status
,带有 _
的 case 语句将作为通配符匹配,并返回“互联网出现问题”。 请注意最后一个块:变量名称 _
充当 通配符 并确保主题始终匹配。 _
的使用是可选的。
您可以使用 |
(“或”)在单个模式中组合多个文字:
case 401 | 403 | 404:
return "Not allowed"
没有通配符的行为
如果我们通过删除最后一个 case 块来修改上面的示例,则示例变为:
def http_error(status):
match status:
case 400:
return "Bad request"
case 404:
return "Not found"
case 418:
return "I'm a teapot"
如果不在 case 语句中使用 _
,则可能不存在匹配项。 如果不存在匹配项,则行为为空操作。 例如,如果通过 500 的 status
,则会发生空操作。
带有文字和变量的模式
模式可能看起来像解包赋值,并且模式可用于绑定变量。 在这个例子中,一个数据点可以解包到它的 x 坐标和 y 坐标:
# point is an (x, y) tuple
match point:
case (0, 0):
print("Origin")
case (0, y):
print(f"Y={y}")
case (x, 0):
print(f"X={x}")
case (x, y):
print(f"X={x}, Y={y}")
case _:
raise ValueError("Not a point")
第一个模式有两个文字,(0, 0)
,可以认为是上面显示的文字模式的扩展。 接下来的两个模式组合了一个文字和一个变量,变量 绑定了 来自主题的值 (point
)。 第四个模式捕获两个值,这使得它在概念上类似于解包赋值 (x, y) = point
。
模式和类
如果您使用类来构造数据,则可以使用类名作为模式,后跟类似于构造函数的参数列表。 此模式能够将类属性捕获到变量中:
class Point:
x: int
y: int
def location(point):
match point:
case Point(x=0, y=0):
print("Origin is the point's location.")
case Point(x=0, y=y):
print(f"Y={y} and the point is on the y-axis.")
case Point(x=x, y=0):
print(f"X={x} and the point is on the x-axis.")
case Point():
print("The point is located somewhere else on the plane.")
case _:
print("Not a point")
具有位置参数的模式
您可以将位置参数与一些为其属性提供排序的内置类一起使用(例如 数据类)。 您还可以通过在类中设置 __match_args__
特殊属性来定义模式中属性的特定位置。 如果设置为 ("x", "y"),则以下模式都是等效的(并且都将 y
属性绑定到 var
变量):
Point(1, var)
Point(1, y=var)
Point(x=1, y=var)
Point(y=var, x=1)
嵌套模式
模式可以任意嵌套。 例如,如果我们的数据是一个简短的点列表,它可以像这样匹配:
match points:
case []:
print("No points in the list.")
case [Point(0, 0)]:
print("The origin is the only point in the list.")
case [Point(x, y)]:
print(f"A single point {x}, {y} is in the list.")
case [Point(0, y1), Point(0, y2)]:
print(f"Two points on the Y axis at {y1}, {y2} are in the list.")
case _:
print("Something else is found in the list.")
复杂模式和通配符
至此,示例在最后一个 case 语句中单独使用了 _
。 通配符可用于更复杂的模式,例如 ('error', code, _)
。 例如:
match test_variable:
case ('warning', code, 40):
print("A warning has been received.")
case ('error', code, _):
print(f"An error {code} occurred.")
在上述情况下,test_variable
将匹配 ('error', code, 100) 和 ('error', code, 800)。
警卫
我们可以将 if
子句添加到模式中,称为“守卫”。 如果守卫为假,match
继续尝试下一个案例块。 请注意,值捕获发生在评估守卫之前:
match point:
case Point(x, y) if x == y:
print(f"The point is located on the diagonal Y=X at {x}.")
case Point(x, y):
print(f"Point is not on the diagonal.")
其他主要特点
其他几个主要功能:
与解包赋值一样,元组和列表模式具有完全相同的含义并且实际上匹配任意序列。 从技术上讲,主题必须是一个序列。 因此,一个重要的例外是模式不匹配迭代器。 此外,为了防止常见错误,序列模式不匹配字符串。
序列模式支持通配符:
[x, y, *rest]
和(x, y, *rest)
的工作方式类似于解包赋值中的通配符。*
后面的名字也可能是_
,所以(x, y, *_)
匹配至少两个item的序列,不绑定剩余的item。映射模式:
{"bandwidth": b, "latency": l}
从字典中捕获"bandwidth"
和"latency"
值。 与序列模式不同,额外的键被忽略。 还支持通配符**rest
。 (但**_
是多余的,所以是不允许的。)可以使用
as
关键字捕获子模式:case (Point(x1, y1), Point(x2, y2) as p2): ...
这将 x1, y1, x2, y2 绑定到主题的整个第二项,就像您在没有
as
子句的情况下所期望的那样。大多数文字通过相等进行比较。 但是,单例
True
、False
和None
是通过身份比较的。命名常量可以在模式中使用。 这些命名常量必须是点名,以防止常量被解释为捕获变量:
from enum import Enum class Color(Enum): RED = 0 GREEN = 1 BLUE = 2 match color: case Color.RED: print("I see red!") case Color.GREEN: print("Grass is green") case Color.BLUE: print("I'm feeling the blues :(")
有关完整规范,请参阅 PEP 634。 动机和基本原理在 PEP 635,更长的教程在 PEP 636。
可选 EncodingWarning 和 encoding="locale" 选项
TextIOWrapper
和 open() 的默认编码取决于平台和语言环境。 由于 UTF-8 用于大多数 Unix 平台,因此在打开 UTF-8 文件时省略 encoding
选项(例如 JSON、YAML、TOML、Markdown)是一个非常常见的错误。 例如:
# BUG: "rb" mode or encoding="utf-8" should be used.
with open("data.json") as f:
data = json.load(f)
为了找到这种类型的错误,添加了一个可选的 EncodingWarning
。 当 sys.flags.warn_default_encoding 为真并且使用特定于语言环境的默认编码时会发出它。
添加了 -X warn_default_encoding
选项和 PYTHONWARNDEFAULTENCODING 以启用警告。
有关详细信息,请参阅 文本编码 。
其他语言更改
- int 类型有一个新方法 int.bit_count(),返回给定整数的二进制展开式中 1 的数量,也称为人口计数。 (由 Niklas Fiekas 在 中提供:issue:`29882`。)
- dict.keys()、dict.values() 和 dict.items() 返回的视图现在都有一个
mapping
属性这给出了一个 types.MappingProxyType 包装原始字典的对象。 (由 Dennis Sweeney 在 中提供:问题:`40890`。) - PEP 618:zip() 函数现在有一个可选的
strict
标志,用于要求所有迭代具有相等的长度。 - 采用整数参数的内置和扩展函数不再接受 Decimals、Fractions 和其他只能在有损失的情况下转换为整数的对象(例如 具有 __int__() 方法但没有 __index__() 方法)。 (由 Serhiy Storchaka 在 中提供:issue:`37999`。)
- 如果 object.__ipow__() 返回 NotImplemented,算子将正确回退到 object.__pow__() 和 object.__rpow__() ] 正如预期的那样。 (由 Alex Shkop 在 中提供:问题:`38302`。)
- 赋值表达式现在可以在集合文字和集合推导式中以及在序列索引(但不是切片)中不加括号地使用。
- 函数有一个新的
__builtins__
属性,用于在函数执行时查找内置符号,而不是查找__globals__['__builtins__']
。 如果存在,则从__globals__["__builtins__"]
初始化该属性,否则从当前内置函数初始化。 (由 Mark Shannon 在 中贡献:issue:`42990`。) - 添加了两个新的内置函数 - aiter() 和
anext()
以分别为 iter() 和 next() 提供异步对应项. (由 Joshua Bronson、Daniel Pope 和 Justin Wang 在 :issue:`31861` 中提供。) - 静态方法 (@staticmethod) 和类方法 (@classmethod) 现在继承方法属性 (
__module__
,__name__
,__qualname__
]、__doc__
、__annotations__
)并有一个新的__wrapped__
属性。 此外,静态方法现在可以作为常规函数调用。 (由 Victor Stinner 在 中提供:问题:`43682`。) - 复杂目标的注释(除 PEP 526 定义的
simple name
目标之外的所有内容)不再对from __future__ import annotations
产生任何运行时影响。 (由 Batuhan Taskaya 在 中贡献:问题:`42737`。) - 类和模块对象现在可以根据需要延迟创建空注释字典。 注释字典存储在对象的
__dict__
中以实现向后兼容。 这改进了使用__annotations__
的最佳实践; 有关更多信息,请参阅 注释最佳实践 。 (由 Larry Hastings 在 中提供:问题:`43901`。) - 注释包含
yield
、yield from
、await
或命名表达式现在由于其副作用而被禁止在from __future__ import annotations
下。 (由 Batuhan Taskaya 在 中提供:issue:`42725`。) - 使用未绑定变量、
super()
和其他可能改变符号表处理的表达式作为注释现在在from __future__ import annotations
下无效。 (由 Batuhan Taskaya 在 中提供:issue:`42725`。) - float 类型和 decimal.Decimal 类型的 NaN 值的哈希值现在取决于对象标识。 以前,它们总是散列到
0
,即使 NaN 值彼此不相等。 在创建包含多个 NaN 的字典和集合时,由于过多的哈希冲突,这可能导致潜在的二次运行时行为。 (由 Raymond Hettinger 在 中提供:issue:`43475`。) - 删除 __debug__ 常量时将引发 SyntaxError(而不是 NameError)。 (由 Dong-hee Na 在 中提供:issue:`45000`。)
- SyntaxError 异常现在具有
end_lineno
和end_offset
属性。 如果未确定,它们将是None
。 (由 Pablo Galindo 在 中提供:issue:`43914`。)
新模块
- 还没有。
改进的模块
参数解析
在 argparse 帮助中,误导性短语“可选参数”被替换为“选项”。 如果某些测试依赖于精确的输出匹配,则可能需要进行调整。 (由 Raymond Hettinger 在 中提供:issue:`9694`。)
大批
array.array 的 index() 方法现在有可选的 start 和 stop 参数。 (由 Anders Lorentsen 和 Zackery Spytz 在 中提供:issue:`31956`。)
base64
添加 base64.b32hexencode() 和 base64.b32hexdecode() 以支持 Base32 Encoding with Extended Hex Alphabet。
收藏.abc
collections.abc.Callable 的 参数化泛型 的 __args__
现在与 typing.Callable 一致。 collections.abc.Callable 泛型现在扁平化类型参数,类似于 typing.Callable 目前所做的。 这意味着collections.abc.Callable[[int, str], str]
将有(int, str, str)
的__args__
; 以前这是 ([int, str], str)
。 为了允许这种更改,现在可以对 types.GenericAlias 进行子类化,并且在为 collections.abc.Callable 类型下标时将返回一个子类。 请注意,对于参数化 collections.abc.Callable 的无效形式,可能会引发 TypeError,这些参数可能已在 Python 3.9 中静默传递。 (由 Ken Jin 在 中提供:issue:`42195`。)
上下文库
添加 contextlib.aclosure() 上下文管理器以安全关闭异步生成器和表示异步释放资源的对象。 (由 Joongi Kim 和 John Belmonte 在 :issue:`41229` 中提供。)
向 contextlib.nullcontext() 添加异步上下文管理器支持。 (由 Tom Gringauz 在 :issue:`41543` 中贡献。)
添加 AsyncContextDecorator
,支持使用异步上下文管理器作为装饰器。
诅咒
ncurses 6.1 中添加的扩展颜色函数将由 curses.color_content()、curses.init_color()、curses.init_pair() 和curses.pair_content()。 新函数 curses.has_extended_color_support() 指示底层 ncurses 库是否提供扩展颜色支持。 (由 Jeffrey Kintscher 和 Hans Petter Jansson 在 中提供:issue:`36982`。)
BUTTON5_*
常量现在在 curses 模块中公开,如果它们是由底层的 curses 库提供的。 (由 Zackery Spytz 在 中提供:issue:`39273`。)
数据类
仅关键字字段
数据类现在支持在生成的 __init__ 方法中只有关键字的字段。 有多种方法可以指定仅限关键字的字段。
你可以说每个字段都是关键字:
from dataclasses import dataclass
@dataclass(kw_only=True)
class Birthday:
name: str
birthday: datetime.date
name
和 birthday
都是生成的 __init__ 方法的关键字参数。
您可以在每个字段的基础上指定仅关键字:
from dataclasses import dataclass
@dataclass
class Birthday:
name: str
birthday: datetime.date = field(kw_only=True)
这里只有 birthday
是仅关键字的。 如果您在单个字段上设置 kw_only
,请注意由于仅关键字字段需要遵循非仅关键字字段,因此存在重新排序字段的规则。 有关详细信息,请参阅完整的数据类文档。
您还可以指定 KW_ONLY 标记后面的所有字段都是关键字。 这可能是最常见的用法:
from dataclasses import dataclass, KW_ONLY
@dataclass
class Point:
x: float
y: float
_: KW_ONLY
z: float = 0.0
t: float = 0.0
这里,z
和 t
是仅关键字参数,而 x
和 y
不是。 (由埃里克 V 提供。 中的史密斯:问题:`43532`)
分配器
整个 distutils
包已弃用,将在 Python 3.12 中删除。 它指定包构建的功能已经被第三方包 setuptools
和 packaging
完全取代,大多数其他常用的 API 都可以在标准库的其他地方使用(例如 platform 、shutil、subprocess 或 sysconfig)。 没有计划从 distutils
迁移任何其他功能,使用其他功能的应用程序应该计划制作代码的私有副本。 参考 PEP 632 讨论。
Python 3.8 中弃用的 bdist_wininst
命令已被删除。 现在建议使用 bdist_wheel
命令在 Windows 上分发二进制包。 (由 Victor Stinner 在 中提供:问题:`42802`。)
文件输入
在 fileinput.input() 和 fileinput.FileInput 中添加 encoding 和 errors 参数。 (由 Inada Naoki 在 中提供:issue:`43712`。)
fileinput.hook_compressed() 现在在 mode 为“r”并且文件被压缩时返回 TextIOWrapper
对象,就像未压缩的文件一样。 (由稻田直树在 中提供:issue:`5758`。)
GC
为 gc.get_objects()、gc.get_referrers() 和 gc.get_referents() 添加审计钩子。 (由 Pablo Galindo 在 中提供:issue:`43439`。)
球体
在 glob() 和 iglob() 中添加 root_dir 和 dir_fd 参数,允许指定搜索的根目录。 (由 Serhiy Storchaka 在 中提供:issue:`38144`。)
哈希库
hashlib 模块需要 OpenSSL 1.1.1 或更新版本。 (由 Christian Heimes 在 PEP 644 和 中提供:issue:`43669`。)
hashlib 模块初步支持 OpenSSL 3.0.0。 (由 Christian Heimes 在 :issue:`38820` 和其他问题中贡献。)
pbkdf2_hmac() 的纯 Python 回退已弃用。 将来 PBKDF2-HMAC 将仅在 Python 构建时支持 OpenSSL 时可用。 (由 Christian Heimes 在 中提供:issue:`43880`。)
空闲和空闲库
让 IDLE 调用 sys.excepthook()(在没有“-n”的情况下启动时)。 用户挂钩以前被忽略。 (Ken Hilton 在 中的补丁:问题:`43008`。)
此更改已向后移植到 3.9 维护版本。
添加 Shell 侧边栏。 将主要提示 ('>>>') 移至侧边栏。 将辅助提示 ('...') 添加到侧边栏。 左键单击和可选的拖动选择一行或多行文本,就像编辑器行号侧边栏一样。 选择文本行后右键单击会显示带有“带提示的复制”的上下文菜单。 这将来自侧边栏的提示与所选文本中的行压缩在一起。 此选项也出现在文本的上下文菜单中。 (由 Tal Einat 在 中提供:问题:`37903`。)
使用空格而不是制表符来缩进交互式代码。 这使得交互式代码条目“看起来正确”。 使这成为可能是添加 shell 侧边栏的主要动机。 由 Terry Jan Reedy 在 中提供:issue:`37892`。)
我们希望将这些 shell 更改向后移植到未来的 3.9 维护版本。
在模式匹配语句中突出显示新的 软关键字 match、case 和 _。 但是,这种突出显示并不完美,在某些极少数情况下会出现错误,包括 case
模式中的某些 _
-s。 (由 Tal Einat 在 bpo-44010 中贡献。)
导入库元数据
与 importlib_metadata
4.6 的功能相同(history)。
importlib.metadata 入口点 现在通过新的 importlib.metadata.EntryPoints
类为按组和名称选择入口点提供更好的体验。 有关弃用和使用的更多信息,请参阅文档中的兼容性说明。
添加了 importlib.metadata.packages_distributions()
,用于将顶级 Python 模块和包解析为它们的 importlib.metadata.Distribution
。
检查
当模块没有定义__loader__
时,回退到__spec__.loader
。 (由 Brett Cannon 在 中贡献:issue:`42133`。)
添加 inspect.get_annotations(),它可以安全地计算对象上定义的注释。 它解决了访问各种类型对象上的注释的怪癖,并对它检查的对象做出很少的假设。 inspect.get_annotations() 也可以正确地取消字符串化注释。 inspect.get_annotations() 现在被认为是访问在任何 Python 对象上定义的注释字典的最佳实践; 有关使用注释的最佳实践的更多信息,请参阅 注释最佳实践 。 相关地,inspect.signature()、inspect.Signature.from_callable() 和 inspect.Signature.from_function()
现在调用 inspect.get_annotations() 来检索注释。 这意味着 inspect.signature() 和 inspect.Signature.from_callable() 现在也可以取消字符串化注释。 (由 Larry Hastings 在 中提供:问题:`43817`。)
操作系统
为 VxWorks RTOS 添加 os.cpu_count() 支持。 (由 Peixing Xin 在 中提供:issue:`41440`。)
添加一个新函数 os.eventfd() 和相关帮助程序,以在 Linux 上封装 eventfd2
系统调用。 (由 Christian Heimes 在 中提供:issue:`41001`。)
添加 os.splice() 允许在两个文件描述符之间移动数据,而无需在内核地址空间和用户地址空间之间进行复制,其中一个文件描述符必须引用管道。 (由 Pablo Galindo 在 中提供:issue:`41625`。)
为 macOS 添加 O_EVTONLY、O_FSYNC、O_SYMLINK 和 O_NOFOLLOW_ANY。 (由 Dong-hee Na 在 中提供:issue:`43106`。)
操作系统路径
os.path.realpath() 现在接受 strict 仅关键字参数。 当设置为 True
时,如果路径不存在或遇到符号链接循环,则会引发 OSError。 (由 Barney Gale 在 中提供:问题:`43757`。)
路径库
向 PurePath.parents 添加切片支持。 (由 Joshua Cannon 在 中提供:issue:`35498`)
向 PurePath.parents 添加负索引支持。 (由 Yaroslav Pankovych 在 中提供:issue:`21041`)
添加取代 link_to() 的 Path.hardlink_to 方法。 新方法的参数顺序与 symlink_to() 相同。 (由 Barney Gale 在 中提供:issue:`39950`。)
pathlib.Path.stat() 和 chmod() 现在接受 follow_symlinks 关键字参数,以与 os 中的相应函数保持一致] 模块。 (由 Barney Gale 在 中提供:问题:`39906`。)
平台
添加 platform.freedesktop_os_release() 以从 freedesktop.org os-release 标准文件中检索操作系统标识。 (由 Christian Heimes 在 中提供:issue:`28468`)
打印
pprint.pprint() 现在接受新的 underscore_numbers
关键字参数。 (由 sblondon 在 中贡献:issue:`42914`。)
pprint 现在可以漂亮地打印 dataclasses.dataclass 实例。 (由 Lewis Gaul 在 中提供:问题:`43080`。)
pyclbr
将 end_lineno
属性添加到 pyclbr.readline()
和 pyclbr.readline_ex()
返回的树中的 Function
和 Class
对象。 它匹配现有的(开始)lineno
。 (由 Aviral Srivastava 在 中提供:issue:`38307`。)
搁置
shelf 模块现在在创建书架时默认使用 pickle.DEFAULT_PROTOCOL 而不是 pickle 协议 3
。 (由 Zackery Spytz 在 中提供:issue:`34204`。)
统计数据
添加 covariance()、Pearson 的 correlation() 和简单的 linear_regression() 函数。 (由 Tymoteusz Wołodźko 在 中提供:issue:`38490`。)
插座
异常 socket.timeout 现在是 TimeoutError 的别名。 (由 Christian Heimes 在 中提供:问题:`42413`。)
添加使用 IPPROTO_MPTCP
创建 MPTCP 套接字的选项(由 Rui Cunha 在 中贡献:issue:`43571`。)
添加 IP_RECVTOS
选项以接收服务类型 (ToS) 或 DSCP/ECN 字段(由 Georg Sauthoff 在 :issue:`44077` 中贡献。)
ssl
ssl 模块需要 OpenSSL 1.1.1 或更新版本。 (由 Christian Heimes 在 PEP 644 和 中提供:issue:`43669`。)
ssl 模块初步支持 OpenSSL 3.0.0 和新选项 OP_IGNORE_UNEXPECTED_EOF。 (由 Christian Heimes 在 :issue:`38820`、:issue:`43794`、:issue:`43788`、:issue 中贡献:`43791`, :issue:`43799`, :issue:`43920`, :issue:`43789`, 和 [X25] ]:问题:`43811`。)
弃用的函数和弃用的常量的使用现在会导致 DeprecationWarning。 ssl.SSLContext.options 默认设置了 OP_NO_SSLv2 和 OP_NO_SSLv3,因此无法警告再次设置标志。 弃用部分 列出了已弃用的功能。 (由 Christian Heimes 在 中提供:issue:`43880`。)
ssl 模块现在具有更安全的默认设置。 默认情况下禁用没有前向保密或 SHA-1 MAC 的密码。 安全级别 2 禁止安全性低于 112 位的弱 RSA、DH 和 ECC 密钥。 SSLContext 默认为最低协议版本 TLS 1.2。 设置基于 Hynek Schlawack 的研究。 (由 Christian Heimes 在 中提供:issue:`43998`。)
不再正式支持已弃用的协议 SSL 3.0、TLS 1.0 和 TLS 1.1。 Python 不会主动阻止它们。 然而,OpenSSL 构建选项、发行版配置、供应商补丁和密码套件可能会阻止成功握手。
将 timeout 参数添加到 ssl.get_server_certificate() 函数。 (由 Zackery Spytz 在 中提供:issue:`31870`。)
ssl 模块使用堆类型和多阶段初始化。 (由 Christian Heimes 在 中提供:issue:`42333`。)
添加了新的验证标志 VERIFY_X509_PARTIAL_CHAIN。 (由 中的 l0x 贡献:问题:`40849`。)
sqlite3
为 connect/handle()
、enable_load_extension() 和 load_extension() 添加审计事件。 (由 Erlend E 提供。 中的 Aasland:问题:`43762`。)
系统
添加 sys.orig_argv 属性:传递给 Python 可执行文件的原始命令行参数列表。 (由 Victor Stinner 在 中提供:问题:`23427`。)
添加 sys.stdlib_module_names,包含标准库模块名称列表。 (由 Victor Stinner 在 中提供:问题:`42955`。)
_线
_thread.interrupt_main() 现在需要一个可选的信号编号来模拟(默认仍然是 signal.SIGINT)。 (由 Antoine Pitrou 在 中提供:issue:`43356`。)
穿线
添加 threading.gettrace() 和 threading.getprofile() 以检索由 threading.settrace() 和 threading.setprofile() 设置的函数 分别。 (由 Mario Corchero 在 中提供:issue:`42251`。)
添加 threading.__excepthook__ 以允许检索 threading.excepthook() 的原始值,以防它设置为损坏或不同的值。 (由 Mario Corchero 在 中提供:issue:`42308`。)
追溯
format_exception()、format_exception_only() 和 print_exception() 函数现在可以将异常对象作为仅位置参数。 (由 Zackery Spytz 和 Matthias Bussonnier 在 :issue:`26389` 中提供。)
类型
重新引入 types.EllipsisType、types.NoneType 和 types.NotImplementedType 类,提供一组易于由类型检查器解释的新类型。 (由 Bas van Beek 在 中提供:问题:`41810`。)
打字
有关主要更改,请参阅 与类型提示相关的新功能 。
typing.Literal 的行为已更改为符合 PEP 586 并匹配 PEP 中指定的静态类型检查器的行为。
Literal
现在删除重复参数。Literal
对象之间的相等比较现在与顺序无关。Literal
比较现在尊重类型。 例如,Literal[0] == Literal[False]
先前评估为True
。 现在是False
。 为了支持此更改,内部使用的类型缓存现在支持区分类型。Literal
对象现在将在相等比较期间引发 TypeError 异常,如果它们的任何参数不是 hashable。 请注意,使用不可散列的参数声明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 在 中提供:issue:`42345`。)
添加新函数 typing.is_typeddict() 以检查注释是否为 typing.TypedDict。 (由 Patrick Reader 在 中提供:问题:`41792`)
仅声明数据变量的 typing.Protocol
的子类现在在使用 isinstance
进行检查时会引发 TypeError
,除非它们用 runtime_checkable()
修饰。 以前,这些检查是静默通过的。 如果用户需要运行时协议,他们应该用 runtime_checkable()
装饰器装饰他们的子类。 (由 Yurii Karabas 在 中提供:issue:`38908`)
从 typing.io
和 typing.re
子模块导入现在将发出 DeprecationWarning。 这些子模块自 Python 3.8 起已被弃用,并将在 Python 的未来版本中删除。 属于这些子模块的任何东西都应该直接从 typing 导入。 (由 Sebastian Rittau 在 中提供:issue:`38291`)
urllib.parse
Python 3.10 之前的 Python 版本允许同时使用 ;
和 &
作为 urllib.parse.parse_qs() 和 urllib.parse.parse_qsl( )。 出于安全考虑,并符合更新的 W3C 建议,这已更改为仅允许单个分隔符键,默认值为 &
。 此更改也会影响 cgi.parse() 和 cgi.parse_multipart(),因为它们在内部使用受影响的函数。 有关更多详细信息,请参阅它们各自的文档。 (由 Adam Goldschmidt、Senthil Kumaran 和 Ken Jin 在 :issue:`42967` 中贡献。)
URL 部分中出现的换行符或制表符允许某些形式的攻击。 遵循更新 RFC 3986、ASCII 换行符 \n
、\r
和制表符 \t
字符的 WHATWG 规范从 URL 中删除由 urllib.parse 中的解析器防止此类攻击。 移除字符由新的模块级变量 urllib.parse._UNSAFE_URL_BYTES_TO_REMOVE
控制。 (参见 :issue:`43882`)
xml
将 LexicalHandler 类添加到 xml.sax.handler 模块。 (由 Jonathan Gossage 和 Zackery Spytz 在 中提供:issue:`35018`。)
压缩导入
添加与PEP 451相关的方法:find_spec()、zipimport.zipimporter.create_module()和zipimport.zipimporter .exec_module()。 (由 Brett Cannon 在 中贡献:问题:`42131`。)
添加 invalidate_caches() 方法。 (由 Desmond Cheong 在 中提供:issue:`14678`。)
优化
- 构造函数 str()、bytes() 和 bytearray() 现在更快(大约 30-40% f 或小对象)。 (由 Serhiy Storchaka 在 中提供:issue:`41334`。)
- runpy 模块现在导入的模块更少。
python3 -m module-name
命令启动时间平均快 1.4 倍。 在 Linux 上,python3 -I -m module-name
在 Python 3.9 上导入 69 个模块,而在 Python 3.10 上仅导入 51 个模块 (-18)。 (由 Victor Stinner 在 :issue:`41006` 和 :issue:`41718` 中贡献。) LOAD_ATTR
指令现在使用新的“每个操作码缓存”机制。 现在常规属性大约为 36% faster,插槽为 44% faster。 (由 Pablo Galindo 和 Yury Selivanov 在 :issue:`42093` 和 Guido van Rossum 在 :issue:`42927` 贡献,基于最初在 PyPy 和 MicroPython 中实现的想法。)- 当使用 --enable-optimizations 构建 Python 时,现在
-fno-semantic-interposition
被添加到编译和链接行。 这将使用 --enable-shared 和gcc
创建的 Python 解释器的构建速度提高了 30%。 详情见这篇文章。 (由 Victor Stinner 和 Pablo Galindo 在 中提供:issue:`38980`。) - bz2 / lzma / zlib模块使用新的输出缓冲区管理代码,并将
.readall()
函数添加到_compression.DecompressReader
类. bz2 解压现在快 1.09x ~ 1.17x,lzma 解压快 1.20x ~ 1.32x,GzipFile.read(-1)
1.11x ~ 1.18x。 (由 Ma Lin 提供,Gregory P. 史密斯,在 :issue:`41486`) - 使用字符串化注释时,创建函数时不再创建函数的注释字典。 相反,它们被存储为一个字符串元组,函数对象根据需要懒惰地将其转换为注释字典。 此优化将定义带注释的函数所需的 CPU 时间减少了一半。 (由 Yurii Karabas 和 Inada Naoki 在 中提供:issue:`42202`)
- 子串搜索功能,例如
str1 in str2
和str2.find(str1)
现在有时会使用 Crochemore & Perrin 的“双向”字符串搜索算法来避免长字符串上的二次行为。 (由 Dennis Sweeney 在 中提供:issue:`41972`) - 对
_PyType_Lookup()
添加微优化,以提高常见缓存命中情况下的类型属性缓存查找性能。 这使解释器平均快 1.04 倍。 (由 Dino Viehland 在 中提供:issue:`43452`) - 以下内置函数现在支持更快的 PEP 590 向量调用约定:map(), filter(), ]reversed()、bool() 和 float()。 (由 Dong-hee Na 和 Jeroen Demeyer 在 :issue:`43575`、:issue:`43287`、:issue:`41922`、 :issue:`41873` 和 :issue:`41870`)
BZ2File
性能通过移除内部RLock
得到改进。 这使得BZ2File
线程在面对多个并发读取器或写入器时不安全,就像 gzip 和 lzma 中的等效类一直都是一样。 (由 Inada Naoki 在 :issue:`43785` 中提供)。
已弃用
目前 Python 接受紧跟关键字的数字文字,例如
0in x
、1or x
、0if 1else 2
。 它允许诸如[0x1for x in y]
(可以解释为[0x1 for x in y]
或[0x1f or x in y]
)之类的混淆和模棱两可的表达。 从此版本开始,如果数字文字后紧跟关键字 和 、else、for、if[ X173X]、 在 、 是 和 或 。 在以后的版本中,它将更改为语法警告,最后更改为语法错误。 (由 Serhiy Storchaka 在 :issue:`43833` 中贡献)。从此版本开始,将齐心协力开始清理为 Python 2.7 兼容性保留的旧导入语义。 具体来说,find_loader()/
find_module()
(由find_spec()
取代),load_module()(由 exec_module() 取代] )、module_repr()(导入系统会为您处理)、__package__
属性(由__spec__.parent
取代)、__loader__
属性(由__spec__.loader
取代),并且__cached__
属性(由__spec__.cached
取代)将被慢慢删除(以及 importlib 中的其他类和方法) )。 ImportWarning 和/或 DeprecationWarning 将被适当提升,以帮助识别在此转换期间需要更新的代码。整个
distutils
命名空间已弃用,将在 Python 3.12 中删除。 有关详细信息,请参阅 模块更改 部分。random.randrange() 的非整数参数已弃用。 ValueError 已弃用,取而代之的是 TypeError。 (由 Serhiy Storchaka 和 Raymond Hettinger 在 中提供:issue:`37319`。)
importlib 的各种
load_module()
方法已被记录为自 Python 3.6 以来已弃用,但现在也会触发 DeprecationWarning。 使用 exec_module() 代替。 (由 Brett Cannon 在 中提供:issue:`26131`。)zimport.zipimporter.load_module()
已弃用 exec_module()。 (由 Brett Cannon 在 中提供:issue:`26131`。)导入系统使用 load_module() 现在会触发 ImportWarning,因为 exec_module() 是首选。 (由 Brett Cannon 在 中提供:issue:`26131`。)
导入系统使用 importlib.abc.MetaPathFinder.find_module() 和 importlib.abc.PathEntryFinder.find_module() 现在触发 ImportWarning 作为 [ X182X]importlib.abc.MetaPathFinder.find_spec() 和 importlib.abc.PathEntryFinder.find_spec() 分别是首选。 您可以使用 importlib.util.spec_from_loader() 来帮助移植。 (由 Brett Cannon 在 中贡献:问题:`42134`。)
导入系统使用 importlib.abc.PathEntryFinder.find_loader() 现在会触发 ImportWarning,因为 importlib.abc.PathEntryFinder.find_spec() 是首选. 您可以使用 importlib.util.spec_from_loader() 来帮助移植。 (由 Brett Cannon 在 中贡献:问题:`43672`。)
importlib.abc.MetaPathFinder.find_module() (
importlib.machinery.BuiltinImporter.find_module()
,importlib.machinery.FrozenImporter.find_module()
,importlib.machinery.WindowsRegistryFinder.find_module()
, importlib.machinery.PathFinder的各种实现。 find_module(), importlib.abc.MetaPathFinder.find_module()), importlib.abc.PathEntryFinder.find_module() (importlib.machinery.FileFinder.find_module()
, ), importlib.abc.PathEntryFinder.find_loader() ( importlib.machinery.FileFinder.find_loader() ) 现在提升 DeprecationWarning 并计划在 Python 3.12 中移除以前它们在 Python 3.4 中被记录为已弃用)。 (由 Brett Cannon 在 中提供:issue:`42135`。)importlib.abc.Finder 已弃用(包括其唯一方法
find_module()
)。 importlib.abc.MetaPathFinder 和 importlib.abc.PathEntryFinder 不再从类继承。 用户应该根据需要从这两个类之一继承。 (由 Brett Cannon 在 中贡献:问题:`42135`。)imp、importlib.find_loader()、
importlib.util.set_package_wrapper()
、importlib.util.set_loader_wrapper()
、importlib.util.module_for_loader()的弃用、pkgutil.ImpImporter 和 pkgutil.ImpLoader 都已更新,将 Python 3.12 列为预定的删除版本(他们开始在以前的版本中提出 DeprecationWarning Python)。 (由 Brett Cannon 在 中贡献:问题:`43720`。)导入系统现在使用模块的
__spec__
属性,然后回退到 module_repr() 模块的__repr__()
方法。 计划在 Python 3.12 中移除module_repr()
的使用。 (由 Brett Cannon 在 中提供:issue:`42137`。)importlib.abc.Loader.module_repr()、
importlib.machinery.FrozenLoader.module_repr()
和importlib.machinery.BuiltinLoader.module_repr()
已弃用并计划在 Python 3.12 中删除。 (由 Brett Cannon 在 中贡献:问题:`42136`。)sqlite3.OptimizedUnicode
自 Python 3.3 起就没有记录和过时,当时它被设为 str 的别名。 它现已弃用,计划在 Python 3.12 中删除。 (由 Erlend E 提供。 中的 Aasland:问题:`42264`。)asyncio.get_event_loop() 如果没有正在运行的事件循环,现在会发出弃用警告。 将来它将是 get_running_loop() 的别名。 asyncio 隐式创建 Future 或 Task 对象的函数现在会在没有运行事件循环和显式 loop 时发出弃用警告传递参数:ensure_future()、wrap_future()、
gather()
、shield()
、as_completed()和构造函数未来、任务、StreamReader、StreamReaderProtocol
。 (由 Serhiy Storchaka 在 中提供:issue:`39529`。)未记录的内置函数
sqlite3.enable_shared_cache
现在已弃用,计划在 Python 3.12 中删除。 SQLite3 文档强烈反对使用它。 有关更多详细信息,请参阅 SQLite3 文档 。 如果必须使用共享缓存,请使用cache=shared
查询参数以 URI 模式打开数据库。 (由 Erlend E 提供。 中的 Aasland:问题:`24464`。)以下
threading
方法现已弃用:threading.currentThread
=> threading.current_thread()threading.activeCount
=> threading.active_count()threading.Condition.notifyAll
=> threading.Condition.notify_all()threading.Event.isSet
=> threading.Event.is_set()threading.Thread.setName
=> threading.Thread.namethreading.thread.getName
=> threading.Thread.namethreading.Thread.isDaemon
=> threading.Thread.daemonthreading.Thread.setDaemon
=> threading.Thread.daemon
(由 Jelle Zijlstra 在 中提供:issue:`21574`。)
pathlib.Path.link_to() 已弃用并计划在 Python 3.12 中删除。 改用 pathlib.Path.hardlink_to()。 (由 Barney Gale 在 中提供:issue:`39950`。)
cgi.log()
已弃用并计划在 Python 3.12 中删除。 (由 Inada Naoki 在 中提供:issue:`41139`。)以下 ssl 功能自 Python 3.6、Python 3.7 或 OpenSSL 1.1.0 起已被弃用,并将在 3.11 中删除:
OP_NO_SSLv2、OP_NO_SSLv3、OP_NO_TLSv1、OP_NO_TLSv1_1、OP_NO_1TLS0_TLSv1_1、OP_NO_1TLS0_1X1_3X1X1X1[X5X1]、[X37X1]、X5X3由
sslSSLContext.minimum_version
和sslSSLContext.maximum_version
。PROTOCOL_SSLv2、PROTOCOL_SSLv3、PROTOCOL_SSLv23、PROTOCOL_TLSv1、PROTOCOL_SSLv3、PROTOCOL_SSLv23PROTOCOL_SSLv1、PRO1TOCOL18、2TLS1_1X1_TLS1_1X8 X159X]PROTOCOL_TLS 已弃用 PROTOCOL_TLS_CLIENT 和 PROTOCOL_TLS_SERVER
RAND_pseudo_bytes(),
RAND_egd()
像 ssl.SSLSocket.selected_npn_protocol() 和 ssl.SSLContext.set_npn_protocols() 等 NPN 功能被 ALPN 取代。
线程调试(PYTHONTHREADDEBUG 环境变量)在 Python 3.10 中已弃用,并将在 Python 3.12 中删除。 此功能需要 Python 的 调试版本。 (由 Victor Stinner 在 中提供:问题:`44584`。)
从
typing.io
和typing.re
子模块导入现在将发出 DeprecationWarning。 这些子模块将在 Python 的未来版本中删除。 属于这些子模块的任何东西都应该直接从 typing 导入。 (由 Sebastian Rittau 在 中提供:issue:`38291`)
已移除
删除了特殊方法
__int__
、__float__
、__floordiv__
、__mod__
、__divmod__
、__rfloordiv__
、__rmod__
] 和 复合体 类的__rdivmod__
。 他们总是引发 TypeError。 (由 Serhiy Storchaka 在 中提供:issue:`41974`。)来自私有和未记录的
_markupbase
模块的ParserBase.error()
方法已被删除。 html.parser.HTMLParser 是ParserBase
的唯一子类,它的error()
实现已经在 Python 3.5 中删除了。 (由 Berker Peksag 在 中提供:issue:`31844`。)删除了
unicodedata.ucnhash_CAPI
属性,它是一个内部 PyCapsule 对象。 相关的私有_PyUnicode_Name_CAPI
结构已移至内部 C API。 (由 Victor Stinner 在 中提供:问题:`42157`。)删除了
parser
模块,该模块因切换到新的 PEG 解析器而在 3.9 中被弃用,以及所有仅由旧解析器使用的 C 源文件和头文件,包括 [ X203X]、parser.h
、graminit.h
和grammar.h
。删除了公共 C API 函数
PyParser_SimpleParseStringFlags
、PyParser_SimpleParseStringFlagsFilename
、PyParser_SimpleParseFileFlags
和PyNode_Compile
,这些函数因切换到新的 PEG 解析器而在 3.9 中被弃用。删除了
formatter
模块,该模块在 Python 3.4 中已弃用。 它有点过时,很少使用,也没有经过测试。 它最初计划在 Python 3.6 中删除,但这种删除被推迟到 Python 2.7 EOL 之后。 现有用户应该将他们使用的任何类复制到他们的代码中。 (由 Dong-hee Na 和 Terry J 提供。 中的 Reedy:问题:`42299`。)删除了
PyModule_GetWarningsModule()
函数,由于 _warnings 模块在 2.6 中被转换为内置模块,因此现在无用。 (由 Hai Shi 在 中提供:issue:`42599`。)从 collections 模块中删除 Collections Abstract Base Classes 的弃用别名。 (由 Victor Stinner 在 中提供:问题:`37324`。)
在 Python 3.8 中弃用后,
loop
参数已从 asyncio 的 高级 API 的大部分中删除。 这种变化背后的动机是多方面的:这简化了高级 API。
自 Python 3.7 以来,高级 API 中的函数已隐式获取当前线程的运行事件循环。 在大多数正常用例中,不需要将事件循环传递给 API。
事件循环传递容易出错,尤其是在处理在不同线程中运行的循环时。
请注意,低级 API 仍将接受
loop
。 有关如何替换现有代码的示例,请参阅 Python API 中的更改 。(由 Yurii Karabas、Andrew Svetlov、Yury Selivanov 和 Kyle Stanley 在 :issue:`42392` 中提供。)
移植到 Python 3.10
本节列出了可能需要更改您的代码的先前描述的更改和其他错误修正。
Python 语法的变化
- 如果数字文字后紧跟关键字(如
0in x
),则在编译以前有效的语法时会发出弃用警告。 在以后的版本中,它将更改为语法警告,最后更改为语法错误。 要消除警告并使代码与未来版本兼容,只需在数字文字和以下关键字之间添加一个空格。 (由 Serhiy Storchaka 在 :issue:`43833` 中贡献)。
Python API 的变化
traceback中的format_exception()、format_exception_only()和print_exception()函数的etype参数] 模块已重命名为 exc。 (由 Zackery Spytz 和 Matthias Bussonnier 在 :issue:`26389` 中提供。)
atexit:在 Python 退出时,如果使用 atexit.register() 注册的回调失败,现在会记录其异常。 以前,只记录一些异常,最后一个异常总是被默默忽略。 (由 Victor Stinner 在 中提供:问题:`42639`。)
collections.abc.Callable 泛型现在扁平化类型参数,类似于 typing.Callable 目前所做的。 这意味着
collections.abc.Callable[[int, str], str]
将有(int, str, str)
的__args__
; 以前这是([int, str], str)
。 通过 typing.get_args() 或__args__
访问参数的代码需要考虑这种变化。 此外,TypeError 可能会因参数化 collections.abc.Callable 的无效形式而引发,这些参数可能已在 Python 3.9 中静默传递。 (由 Ken Jin 在 中提供:issue:`42195`。)socket.htons() 和 socket.ntohs() 现在提高 OverflowError 而不是 DeprecationWarning 如果给定的参数不适合16 位无符号整数。 (由 Erlend E 提供。 中的 Aasland:问题:`42393`。)
在 Python 3.8 中弃用后,
loop
参数已从 asyncio 的 高级 API 的大部分中删除。目前看起来像这样的协程:
async def foo(loop): await asyncio.sleep(1, loop=loop)
应该替换成这样:
async def foo(): await asyncio.sleep(1)
如果
foo()
是专门设计的 not 在当前线程的运行事件循环中运行(例如 在另一个线程的事件循环中运行),请考虑使用 asyncio.run_coroutine_threadsafe() 代替。(由 Yurii Karabas、Andrew Svetlov、Yury Selivanov 和 Kyle Stanley 在 :issue:`42392` 中提供。)
如果 globals 字典没有
"__builtins__"
键,则 types.FunctionType 构造函数现在继承当前的内置函数,而不是使用{"None": None}
作为内置函数:相同的行为作为 eval() 和 exec() 函数。 在 Python 中用def function(...): ...
定义一个函数不受影响,全局变量不能被这个语法覆盖:它也继承了当前的内置函数。 (由 Victor Stinner 在 中提供:问题:`42990`。)
C API 的变化
C API 函数
PyParser_SimpleParseStringFlags
、PyParser_SimpleParseStringFlagsFilename
、PyParser_SimpleParseFileFlags
、PyNode_Compile
和这些函数使用的类型struct _node
被删除切换到新的 PEG 解析器。现在应该使用例如 Py_CompileString() 将源代码直接编译为代码对象。 然后可以使用例如 PyEval_EvalCode() 评估生成的代码对象。
具体来说:
对
PyParser_SimpleParseStringFlags
后跟PyNode_Compile
的调用可以通过调用 Py_CompileString() 来代替。PyParser_SimpleParseFileFlags
没有直接替代品。 要从FILE *
参数编译代码,您需要在 C 中读取文件并将结果缓冲区传递给 Py_CompileString()。要编译给定
char *
文件名的文件,请显式打开该文件,读取它并编译结果。 一种方法是使用 io 模块与 PyImport_ImportModule()、PyObject_CallMethod()、PyBytes_AsString()[X145X] 和 [X145X] Py_CompileString(),如下所示。 (省略了声明和错误处理。)io_module = Import_ImportModule("io"); fileobject = PyObject_CallMethod(io_module, "open", "ss", filename, "rb"); source_bytes_object = PyObject_CallMethod(fileobject, "read", ""); result = PyObject_CallMethod(fileobject, "close", ""); source_buf = PyBytes_AsString(source_bytes_object); code = Py_CompileString(source_buf, filename, Py_file_input);
对于
FrameObject
对象,f_lasti
成员现在表示字码偏移量,而不是字节码字符串中的简单偏移量。 这意味着这个数字需要乘以 2 才能与期望字节偏移的 API 一起使用(例如 PyCode_Addr2Line())。 还要注意FrameObject
对象的f_lasti
成员被认为是不稳定的:请改用 PyFrame_GetLineNumber()。
CPython 字节码更改
MAKE_FUNCTION
指令现在接受一个 dict 或一个字符串元组作为函数的注释。 (由 Yurii Karabas 和 Inada Naoki 在 中提供:issue:`42202`)
构建更改
PEP 644:Python 现在需要 OpenSSL 1.1.1 或更新版本。 不再支持 OpenSSL 1.0.2。 (由 Christian Heimes 在 中提供:issue:`43669`。)
现在需要 C99 函数
snprintf()
和vsnprintf()
来构建 Python。 (由 Victor Stinner 在 中提供:问题:`36020`。)sqlite3 需要 SQLite 3.7.15 或更高版本。 (由谢尔盖 Fedoseev 和 Erlend E. 供稿。 Aasland :issue:`40744` 和 :issue:`40810`。)
atexit 模块现在必须始终构建为内置模块。 (由 Victor Stinner 在 中提供:问题:`42639`。)
将 --disable-test-modules 选项添加到
configure
脚本:不要构建或安装测试模块。 (由 Xavier de Gaye、Thomas Petazzoni 和 Peixing Xin 在 :issue:`27640` 中提供。)将 --with-wheel-pkg-dir=PATH 选项 添加到
./configure
脚本。 如果指定,ensurepip 模块在此目录中查找setuptools
和pip
轮包:如果两者都存在,则使用这些轮包而不是 ensurepip 捆绑轮包。一些 Linux 分发打包策略建议不要捆绑依赖项。 比如Fedora在
/usr/share/python-wheels/
目录下安装wheel包,不安装ensurepip._bundled
包。(由 Victor Stinner 在 中提供:问题:`42856`。)
添加新的 configure --without-static-libpython 选项 以不构建
libpythonMAJOR.MINOR.a
静态库并且不安装python.o
目标文件。(由 Victor Stinner 在 中提供:问题:`43103`。)
configure
脚本现在使用pkg-config
实用程序(如果可用)来检测 Tcl/Tk 头文件和库的位置。 和以前一样,可以使用 --with-tcltk-includes 和 --with-tcltk-libs 配置选项明确指定这些位置。 (由 Manolis Stamatogiannakis 在 :issue:`42603` 中提供。)将 --with-openssl-rpath 选项添加到
configure
脚本。 该选项简化了使用自定义 OpenSSL 安装构建 Python,例如./configure --with-openssl=/path/to/openssl --with-openssl-rpath=auto
。 (由 Christian Heimes 在 中提供:issue:`43466`。)
C API 更改
PEP 652:保持稳定的 ABI
现在明确定义了用于扩展模块或嵌入 Python 的稳定 ABI(应用程序二进制接口)。 C API 稳定性 描述了 C API 和 ABI 稳定性保证以及使用稳定 ABI 的最佳实践。
(由 Petr Viktorin 在 PEP 652 和 :issue:`43795` 中贡献。)
新功能
PyNumber_Index() 的结果现在总是具有精确的类型 int。 以前,结果可能是
int
的子类的实例。 (由 Serhiy Storchaka 在 中提供:issue:`40792`。)将新的 orig_argv 成员添加到 PyConfig 结构:传递给 Python 可执行文件的原始命令行参数列表。 (由 Victor Stinner 在 中提供:问题:`23427`。)
添加了 PyDateTime_DATE_GET_TZINFO() 和 PyDateTime_TIME_GET_TZINFO() 宏,用于访问 datetime.datetime 的
tzinfo
属性。时间 对象。 (由 Zackery Spytz 在 中提供:issue:`30155`。)添加 PyCodec_Unregister() 函数以注销编解码器搜索函数。 (由 Hai Shi 在 中提供:issue:`41842`。)
添加了 PyIter_Send() 函数以允许将值发送到迭代器而不会引发
StopIteration
异常。 (由 Vladimir Matveev 在 :issue:`41756` 中提供。)将 PyUnicode_AsUTF8AndSize() 添加到有限的 C API。 (由 Alex Gaynor 在 :issue:`41784` 中提供。)
添加 PyModule_AddObjectRef() 函数:类似于 PyModule_AddObject() 但不要在成功时窃取对值的引用。 (由 Victor Stinner 在 中提供:问题:`1635741`。)
添加 Py_NewRef() 和 Py_XNewRef() 函数来增加对象的引用计数并返回对象。 (由 Victor Stinner 在 中提供:问题:`42262`。)
PyType_FromSpecWithBases() 和 PyType_FromModuleAndSpec() 函数现在接受单个类作为 bases 参数。 (由 Serhiy Storchaka 在 中提供:issue:`42423`。)
PyType_FromModuleAndSpec() 函数现在接受 NULL
tp_doc
插槽。 (由 Hai Shi 在 中提供:issue:`41832`。)PyType_GetSlot() 函数可以接受 静态类型 。 (由 Hai Shi 和 Petr Viktorin 在 中提供:issue:`41073`。)
向 C-API 添加一个新的 PySet_CheckExact() 函数,以检查对象是否是 set 的实例,但不是子类型的实例。 (由 Pablo Galindo 在 中提供:issue:`43277`。)
添加 PyErr_SetInterruptEx() 允许传递信号编号进行模拟。 (由 Antoine Pitrou 在 中提供:issue:`43356`。)
如果 Python 在调试模式 下构建(如果定义了
Py_DEBUG
宏),则现在支持有限的 C API。 在有限的 C API 中,Py_INCREF() 和 Py_DECREF() 函数现在实现为不透明的函数调用,而不是直接访问 PyObject.ob_refcnt 成员, 如果 Python 在调试模式下构建并且Py_LIMITED_API
宏针对 Python 3.10 或更新版本。 在调试模式下支持有限的 C API 成为可能,因为 PyObject 结构自 Python 3.8 起在发布和调试模式下是相同的(参见 :issue:`36465`)。--with-trace-refs 特殊版本(
Py_TRACE_REFS
宏)仍然不支持有限的 C API。 (由 Victor Stinner 在 中提供:问题:`43688`。)添加 Py_Is(x, y) 函数,测试 x 对象是否为 y 对象,与 Python 中的
x is y
相同。 还添加 Py_IsNone(), Py_IsTrue(), Py_IsFalse() 函数来分别测试一个对象是否是None
单例,True
单例或False
单例。 (由 Victor Stinner 在 中提供:问题:`43753`。)添加新函数以从 C 代码控制垃圾收集器:PyGC_Enable()、PyGC_Disable()、PyGC_IsEnabled()。 这些函数允许从 C 代码激活、停用和查询垃圾收集器的状态,而无需导入 gc 模块。
添加新的
Py_TPFLAGS_DISALLOW_INSTANTIATION
类型标志以禁止创建类型实例。 (由 Victor Stinner 在 中提供:问题:`43916`。)添加新的
Py_TPFLAGS_IMMUTABLETYPE
类型标志用于创建不可变类型对象:类型属性不能设置或删除。 (由 Victor Stinner 和 Erlend E. 提供。 中的 Aasland:问题:`43908`。)
移植到 Python 3.10
PY_SSIZE_T_CLEAN
宏现在必须定义为使用 PyArg_ParseTuple() 和 Py_BuildValue() 使用#
的格式:es#
,et#
、s#
、u#
、y#
、z#
、U#
和[X2225X] 请参阅 解析参数和构建值 和 PEP 353。 (由 Victor Stinner 在 中提供:问题:`40943`。)由于 Py_REFCNT() 更改为内联静态函数,因此
Py_REFCNT(obj) = new_refcnt
必须替换为Py_SET_REFCNT(obj, new_refcnt)
:参见 Py_SET_REFCNT()(自 Python 3.9 起可用)。 为了向后兼容,可以使用这个宏:#if PY_VERSION_HEX < 0x030900A4 # define Py_SET_REFCNT(obj, refcnt) ((Py_REFCNT(obj) = (refcnt)), (void)0) #endif
(由 Victor Stinner 在 中提供:问题:`39573`。)
由于历史原因,在不持有 GIL 的情况下调用 PyDict_GetItem() 是被允许的。 它不再被允许。 (由 Victor Stinner 在 中提供:问题:`40839`。)
PyUnicode_FromUnicode(NULL, size)
和PyUnicode_FromStringAndSize(NULL, size)
现在提升DeprecationWarning
。 使用 PyUnicode_New() 分配没有初始数据的 Unicode 对象。 (由 Inada Naoki 在 中提供:issue:`36346`。)PyCapsule API
unicodedata.ucnhash_CAPI
的私有_PyUnicode_Name_CAPI
结构已移至内部 C API。 (由 Victor Stinner 在 中提供:问题:`42157`。)Py_GetPath()、Py_GetPrefix()、Py_GetExecPrefix()、Py_GetProgramFullPath()、和Py_GetExecPrefix() Py_GetProgramName() 函数现在返回
NULL
如果在 Py_Initialize() 之前调用(在 Python 初始化之前)。 使用新的 Python 初始化配置 API 获取 Python 路径配置。。 (由 Victor Stinner 在 中提供:问题:`42260`。)PyList_SET_ITEM()、PyTuple_SET_ITEM() 和 PyCell_SET() 宏不能再用作 l 值或 r 值。 例如,
x = PyList_SET_ITEM(a, b, c)
和PyList_SET_ITEM(a, b, c) = x
现在因编译器错误而失败。 它可以防止像if (PyList_SET_ITEM (a, b, c) < 0) ...
测试这样的错误。 (由 Zackery Spytz 和 Victor Stinner 在 中提供:issue:`30459`。)非限制 API 文件
odictobject.h
、parser_interface.h
、picklebufobject.h
、pyarena.h
、pyctype.h
、pydebug.h
、pyfpe.h
和pytime.h
已移至Include/cpython
目录。 这些文件不能直接包含,因为它们已经包含在Python.h
: Include Files 中。 如果它们已被直接包含,请考虑改为包含Python.h
。 (由 Nicholas Sim 在 中提供:issue:`35134`)使用
Py_TPFLAGS_IMMUTABLETYPE
类型标志创建不可变类型对象。 不要依赖Py_TPFLAGS_HEAPTYPE
来决定类型对象是否可变; 检查是否设置了Py_TPFLAGS_IMMUTABLETYPE
。 (由 Victor Stinner 和 Erlend E. 提供。 中的 Aasland:问题:`43908`。)未记录的函数
Py_FrozenMain
已从有限的 API 中删除。 该函数主要用于 Python 的自定义构建。 (由 Petr Viktorin 在 中提供:issue:`26241`)
已弃用
PyUnicode_InternImmortal()
函数现已弃用,并将在 Python 3.12 中删除:改用 PyUnicode_InternInPlace()。 (由 Victor Stinner 在 中提供:问题:`41692`。)
已移除
删除了操作
Py_UNICODE*
字符串的Py_UNICODE_str*
函数。 (由 Inada Naoki 在 中提供:issue:`41123`。)Py_UNICODE_strlen
:使用 PyUnicode_GetLength() 或 PyUnicode_GET_LENGTHPy_UNICODE_strcat
:使用 PyUnicode_CopyCharacters() 或 PyUnicode_FromFormat()Py_UNICODE_strcpy
、Py_UNICODE_strncpy
:使用 PyUnicode_CopyCharacters() 或 PyUnicode_Substring()Py_UNICODE_strcmp
:使用 PyUnicode_Compare()Py_UNICODE_strncmp
:使用 PyUnicode_Tailmatch()Py_UNICODE_strchr
、Py_UNICODE_strrchr
:使用 PyUnicode_FindChar()
移除
PyUnicode_GetMax()
。 请迁移到新的 (PEP 393) API。 (由 Inada Naoki 在 中提供:issue:`41103`。)移除
PyLong_FromUnicode()
。 请迁移到 PyLong_FromUnicodeObject()。 (由 Inada Naoki 在 中提供:issue:`41103`。)移除
PyUnicode_AsUnicodeCopy()
。 请使用 PyUnicode_AsUCS4Copy() 或 PyUnicode_AsWideCharString()(由 Inada Naoki 在 中贡献:问题:`41103`。)删除了
_Py_CheckRecursionLimit
变量:它已被 PyInterpreterState 结构的ceval.recursion_limit
替换。 (由 Victor Stinner 在 中提供:问题:`41834`。)删除了未记录的宏
Py_ALLOW_RECURSION
和Py_END_ALLOW_RECURSION
以及 PyInterpreterState 结构的recursion_critical
字段。 (由 Serhiy Storchaka 在 中提供:issue:`41936`。)删除了未记录的
PyOS_InitInterrupts()
函数。 初始化 Python 已经隐式安装信号处理程序:参见 PyConfig.install_signal_handlers。 (由 Victor Stinner 在 中提供:问题:`41713`。)删除
PyAST_Validate()
功能。 不再可能使用公共 C API 构建 AST 对象(mod_ty
类型)。 该函数已从有限的 C API (PEP 384) 中排除。 (由 Victor Stinner 在 中提供:问题:`43244`。)删除
symtable.h
头文件和未记录的函数:PyST_GetScope()
PySymtable_Build()
PySymtable_BuildObject()
PySymtable_Free()
Py_SymtableString()
Py_SymtableStringObject()
Py_SymtableString()
函数错误地是稳定 ABI 的一部分,但它无法使用,因为symtable.h
头文件被排除在有限的 C API 之外。改用 Python symtable 模块。 (由 Victor Stinner 在 中提供:问题:`43244`。)
从有限的 C API 头文件和
python3.dll
(在 Windows 上提供稳定 ABI 的库)中删除 PyOS_ReadlineFunctionPointer()。 由于该函数采用FILE*
参数,因此无法保证其 ABI 稳定性。 (由 Petr Viktorin 在 中提供:issue:`43868`。)删除
ast.h
、asdl.h
和Python-ast.h
头文件。 这些函数没有记录并且被排除在有限的 C API 之外。 这些头文件定义的大多数名称都没有以Py
为前缀,因此可能会造成名称冲突。 例如,Python-ast.h
定义了一个Yield
宏,该宏与 Windows<winbase.h>
标头使用的Yield
名称冲突。 请改用 Python ast 模块。 (由 Victor Stinner 在 中提供:问题:`43244`。)删除使用
struct _mod
类型的编译器和解析器函数,因为公共 AST C API 被删除:PyAST_Compile()
PyAST_CompileEx()
PyAST_CompileObject()
PyFuture_FromAST()
PyFuture_FromASTObject()
PyParser_ASTFromFile()
PyParser_ASTFromFileObject()
PyParser_ASTFromFilename()
PyParser_ASTFromString()
PyParser_ASTFromStringObject()
这些函数没有记录并且被排除在有限的 C API 之外。 (由 Victor Stinner 在 中提供:问题:`43244`。)
删除带有函数的
pyarena.h
头文件:PyArena_New()
PyArena_Free()
PyArena_Malloc()
PyArena_AddPyObject()
这些函数没有记录在案,被排除在有限的 C API 之外,并且仅由编译器在内部使用。 (由 Victor Stinner 在 中提供:问题:`43244`。)
PyThreadState.use_tracing
成员已被删除以优化 Python。 (由 Mark Shannon 在 中贡献:问题:`43760`。)