Python 3.10 有什麼新功能¶
- 編輯者:
Pablo Galindo Salgado
本文介紹了 Python 3.10 與 3.9 相比的新功能。Python 3.10 於 2021 年 10 月 4 日發布。有關完整詳細資訊,請參閱 changelog。
摘要 -- 發布重點¶
新增語法特性:
PEP 634,結構模式匹配 (Structural Pattern Matching):規範
PEP 635,結構模式匹配:動機和基本原理
PEP 636,結構模式匹配:教學
bpo-12782,現在正式允許帶括號的情境管理器 (context manager)。
標準函式庫中的新功能:
PEP 618,新增可選的長度檢查到 zip。
直譯器改進:
PEP 626,用於除錯和其他工具的精確列號。
新的 typing 功能:
PEP 604,允許將聯集型別 (union types) 寫為 X | Y
PEP 612,參數規範變數 (Parameter Specification Variables)
PEP 613,顯式型別別名 (Explicit Type Aliases)
PEP 647,使用者定義的型別防護 (User-Defined Type Guards)
重要的棄用、刪除或限制:
新功能¶
帶括號的情境管理器¶
現在支援使用成對的括號來將多個情境管理器以數行表示。這允許了與過去的引入陳述式 (import statement) 類似的方法來格式化一組多行的情境管理器集合。例如,以下範例現在都是有效的:
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 在 bpo-12782 和 bpo-40334 中貢獻。)
更好的錯誤訊息¶
SyntaxErrors¶
當剖析包含未成對括號或方括號的程式碼時,直譯器現在會包含未成對括號的位置,而不是顯示 SyntaxError: unexpected EOF while parsing 或指向某些不正確的位置。例如,以下程式碼(注意未閉合的 {
):
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 在 bpo-42864 和 Batuhan Taskaya 在 bpo-40176 中貢獻。)
直譯器引發的 SyntaxError
例外現在會突顯 (highlight) 構成語法錯誤之運算式的完整錯誤範圍,而不僅是檢測到問題的位置。如此一來,過去(像 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 在 bpo-43914 中貢獻。
已合併了大量針對 SyntaxError
例外的新專用訊息。一些最值得注意的如下:
在區塊之前缺少
:
:>>> if rocket.position > event_horizon File "<stdin>", line 1 if rocket.position > event_horizon ^ SyntaxError: expected ':'
(由 Pablo Galindo 在 bpo-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 在 bpo-43017 中貢獻。)
容器字面值 (collection literals) 中和運算式之間缺少逗號:
>>> items = { ... x: 1, ... y: 2 ... z: 3, File "<stdin>", line 3 y: 2 ^ SyntaxError: invalid syntax. Perhaps you forgot a comma?
(由 Pablo Galindo 在 bpo-43822 中貢獻。)
不帶括號的多個例外型別:
>>> try: ... build_dyson_sphere() ... except NotEnoughScienceError, NotEnoughResourcesError: File "<stdin>", line 3 except NotEnoughScienceError, NotEnoughResourcesError: ^ SyntaxError: multiple exception types must be parenthesized
(由 Pablo Galindo 在 bpo-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 在 bpo-43823 中貢獻。)
沒有
except
或finally
區塊的try
區塊:>>> try: ... x = 2 ... something = 3 File "<stdin>", line 3 something = 3 ^^^^^^^^^ SyntaxError: expected 'except' or 'finally' block
(由 Pablo Galindo 在 bpo-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 在 bpo-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 在 bpo-41064 中貢獻。)
IndentationErrors¶
許多 IndentationError
例外現在支援更多關於哪種區塊需要縮進的情境,包括陳述式的位置:
>>> def foo():
... if lel:
... x = 2
File "<stdin>", line 3
x = 2
^
IndentationError: expected an indented block after 'if' statement in line 2
AttributeErrors¶
當印出 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 在 bpo-38530 中貢獻。)
警告
請注意,如果未呼叫 PyErr_Display()
來顯示錯誤(可能為了要使用其他自定義錯誤顯示函式),則此操作將不起作用。這是 IPython 等某些 REPL 中的常見狀況。
NameErrors¶
當印出直譯器引發的 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 在 bpo-38530 中貢獻。)
警告
請注意,如果未呼叫 PyErr_Display()
來顯示錯誤,則此操作將不起作用,如果使用其他自定義錯誤顯示函式,則可能會發生這種情況。這是 IPython 等某些 REPL 中的常見場景。
PEP 626:用於除錯和其他工具的精確列號¶
PEP 626 為除錯、分析 (profiling) 和覆蓋 (coverage) 工具帶來了更精確、更可靠的列號 (line numbers)。為所有已執行的程式碼列且僅針對已執行的程式碼行產生具有正確列號的追蹤事件。
帧对象的 f_lineno
属性将总是包含预期的行号。
代码对象 的的 co_lnotab
属性已被弃用并将在 3.12 中被移除。 需要从偏移量转换为行号的代码应当改用新的 co_lines()
方法。
PEP 634:結構模式匹配¶
已新增結構模式匹配 (structural pattern matching),其形式為具有關聯操作之模式的 match 陳述式 和 case 陳述式。模式由序列、對映、原始資料型別 (primitive data types) 以及類別實例組成。模式匹配使程式能夠從複雜的資料型別中提取資訊,在資料結構上進行分支,並根據不同形式的資料應用特定的操作。
語法和操作¶
模式匹配的通用語法是:
match subject:
case <pattern_1>:
<action_1>
case <pattern_2>:
<action_2>
case <pattern_3>:
<action_3>
case _:
<action_wildcard>
match 陳述式採用一個運算式,並將其值與作為一個或多個 case 區塊給出的連續模式進行比較。具體來說,模式匹配是透過以下方式進行操作:
使用具有型態 (type) 和特徵 (shape) 的資料 (主語
subject
)match
陳述式中subject
的求值 (evaluating)從上到下將主語與
case
陳述式中的每個模式進行比較,直到確認匹配。執行與已確認匹配模式對應的操作
如果未確認完全匹配,則最後一種情況,即萬用字元
_
(如果有提供)將作為匹配到的情況。如未有任何匹配且不存在萬用字元的 case,則整個 match 區塊會是個無操作 (no-op)。
宣告式方法 (Declarative approach)¶
讀者可能會透過使用 C、Java 或 JavaScript(以及許多其他語言)中的 switch 陳述式將主語(資料物件)與字面值 (literal)(模式)進行匹配的簡單範例來了解模式匹配。 switch 語句通常用於將物件/運算式與包含字面值的 case 陳述式進行比較。
更強大的模式匹配範例可以在 Scala 和 Elixir 等語言中找到。對於結構模式匹配,該方法是「宣告式的 (declarative)」,並且明確地說明了資料匹配的條件(模式)。
雖然使用巢狀 "if" 陳述式的「命令式 (imperative)」指令系列可用於完成類似於結構模式匹配的操作,但它不如「聲明式 (declarative)」方法清晰。相反地,「聲明式」方法規定了匹配所需滿足的條件,並且因其明確表達模式而更具可讀性。雖然結構模式匹配可以用其最簡單的形式達成,將變數與 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
,則回傳 "I'm a teapot"。如果上面的函式傳遞了 500 status
,則帶有 _
的 case 語句將作為萬用字元進行匹配,並回傳 "Something's wrong with the internet"。請注意最後一個區塊:變數名稱 _
充當 萬用字元 並確保主語始終匹配。_
的使用是可選的。
你可以使用 |
("or") 將多個字面值組合在一個模式中:
case 401 | 403 | 404:
return "Not allowed"
沒有萬用字元 (wildcard) 的行為¶
如果我們透過刪除最後一個 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 陳述式中不使用 _
,則可能不存在匹配項目。如果不存在匹配項目,則該行為是無操作 (no-op)。例如,如果 status
為 500,則不會有任何操作。
具有字面值和變數的模式¶
模式看起來就像解包賦值 (unpacking assignment),並且模式可用於繫結 (bind) 變數。在此範例中,可以將資料點解包為其 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")
具有位置參數的模式¶
你可以將位置參數與一些會為其屬性排序的內建類別(例如 dataclasses)一起使用。你還可以通過在類別中設定 __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.")
在上述情況下,值像是 ('error', code, 100) 和 ('error', code, 800) 的 test_variable
將會成功匹配。
Guard¶
我們可以在模式中新增一個 if
子句,稱為 "guard"。如果 guard 為 false,則 match
會繼續嘗試下一個 case 區塊。請注意,值的捕獲發生在 guard 的求值 (evaluate) 之前:
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.")
其他主要功能¶
其他幾個主要功能:
與賦值的解包一樣,tuple 和 list 模式具有完全相同的含義,並且實際上匹配任意序列。從技術上來說,主語必須是一個序列。因此,一個重要的例外是模式不會去匹配疊代器。另外,為了防止常常出錯,序列模式也不會去匹配字串。
序列模式支援萬用字元:
[x, y, *rest]
和(x, y, *rest)
與解包賦值中的萬用字元類似。*
後面的名稱也可能是_
,因此(x, y, *_)
會匹配至少兩個項目的序列,且不繫結其餘項目。對映模式:
{"bandwidth": b, "latency": l}
從字典中捕獲"bandwidth"
和"latency"
值。與序列模式不同,額外的鍵將被忽略。也支援萬用字元**rest
。(但是**_
是多餘的,所以是不允許的。)可以使用
as
關鍵字捕獲子模式:case (Point(x1, y1), Point(x2, y2) as p2): ...
這將繫結 x1、y1、x2、y2,如同沒有
as
子句的情況下所預期的,並將 p2 繫結到主語的整個第二項目。大多數字面值都是通過相等進行比較的。然而,單例
True
、False
和None
是按標識值 (identity) 來進行比較的。附名常數 (named constant) 可以在模式中使用。這些附名常數必須有帶有點的名稱 (dotted name),以防止常數被直譯為捕獲的變數:
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 :(")
可選的 EncodingWarning
和 encoding="locale"
選項¶
TextIOWrapper
和 open()
的預設編碼取決於平台和區域設定。由於大多數 Unix 平台都使用 UTF-8,因此在打開 UTF-8 檔案(例如 JSON、YAML、TOML、Markdown)時省略 encoding
選項是個常見的 bug,例如:
# 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
為 true 且使用特定於語言環境的預設編碼時,會發出該信號。
新增 -X warn_default_encoding
選項和 PYTHONWARNDEFAULTENCODING
來啟用警告。
更多資訊請見 文字編碼。
其他語言變化¶
int
型別有一個新方法int.bit_count()
,回傳給定整數的二進位展開式中 1 的數量,也稱為總體計數 (population count)。(由 Niklas Fiekas 在 bpo-29882 中貢獻。)dict.keys()
、dict.values()
和dict.items()
回傳的視圖 (view) 現在都有一個mapping
屬性,該屬性提供types.MappingProxyType
包裝原始的字典物件。(由 Dennis Sweeney 在 bpo-40890 中貢獻。)採用整數引數的內建函式和擴充函式不再接受
Decimal
、Fraction
以及其他只能在有損失的情況下轉換為整數的物件(例如有__int__()
方法,但沒有__index__()
方法)。(由 Serhiy Storchaka 在 bpo-37999 中貢獻。)如果
object.__ipow__()
返回NotImplemented
,该运算符将按照预期正确地回退至object.__pow__()
和object.__rpow__()
。 (由 Alex Shkop 在 bpo-38302 中贡献。)現在可以在集合字面值 (set literals) 和集合綜合運算 (set comprehensions) 以及序列索引(但不能是切片)中使用不帶括號的賦值運算式 (assignment expressions)。
函式有一個新的
__builtins__
屬性,用於在執行函式時查找內建符號,而不是查找__globals__['__builtins__']
。如果__globals__["__builtins__"]
存在,則屬性會以此做初始化,否則從當前內建物件 (builtins) 初始化。(由 Mark Shannon 在 bpo-42990 中貢獻。)新增兩個內建函式 --
aiter()
和anext()
,分別為iter()
和next()
提供非同步的對應函式。(由 Joshua Bronson、Daniel Pope 和 Justin Wang 在 bpo-31861 中貢獻。)靜態方法 (
@staticmethod
) 和類別方法 (@classmethod
) 現在繼承方法屬性 (__module__
,__name__
,__qualname__
,__doc__
,__annotations__
) 並有一個新的__wrapped__
屬性。此外,靜態方法現在可以像是常規函式般呼叫。(由 Victor Stinner 在 bpo-43682 中貢獻。)複雜目標(除 PEP 526 定義的
simple name
目標之外的所有內容)的註釋不再使用from __future__ import comments
造成任何執行環境 (runtime) 影響。(由 Batuhan Taskaya 在 bpo-42737 中貢獻。)類別和模組物件現在會根據需求來延遲建立 (lazy-create) 空的註釋字典 (annotations dicts)。註釋字典存儲在物件的
__dict__
中以達成向後相容性。這改進了__annotations__
使用方式的最佳實踐方法;有關更多資訊,請參閱 注解最佳实践。(由 Larry Hastings 在 bpo-43901 中貢獻。)附名運算式或由
yield
、yield from
、await
組成的註釋現在在from __future__ import comments
下被禁止,因為它們有些不預期的行為。(由 Batuhan Taskaya 在 bpo-42725 中貢獻。)未繫結變數 (unbound variable)、
super()
和其他可能會改變處理註釋之符號表 (symbol table) 的運算式,現在在from __future__ import comments
下變得無效。(由 Batuhan Taskaya 在 bpo-42725 中貢獻。)float
型別和decimal.Decimal
型別的 NaN 值的雜湊值現在取決於物件的標識值 (identity)。以前即使 NaN 值彼此不相等,它們也總是被雜湊為0
。由於在建立包含多個 NaN 的字典和集合時出現過多的雜湊衝突 (hash collision),可能導致潛在的二次方執行環境行為 (quadratic runtime behavior)。(由 Raymond Hettinger 在 bpo-43475 中貢獻。)当删除
__debug__
常量时将引发SyntaxError
(而不是NameError
)。 (由 Donghee Na 在 bpo-45000 中贡献。)SyntaxError
例外現在具有end_lineno
和end_offset
屬性。如果未被決定,它們將會是None
。(由 Pablo Galindo 在 bpo-43914 中貢獻。)
新模組¶
无。
改進的模組¶
asyncio¶
新增缺少的 connect_accepted_socket()
方法。(由 Alex Grönholm 在 bpo-41332 中貢獻。)
argparse¶
argparse 幫助中的誤導性用詞「可選引數 (optional arguments)」已被替換為「選項 (options)」。某些依賴於精確輸出匹配的測試可能需要進行調整。(由 Raymond Hettinger 在 bpo-9694 中貢獻。)
array¶
array.array
的 index()
方法現在具有可選的 start 和 stop 參數。(由 Anders Lorentsen 和 Zackery Spytz 在 bpo-31956 中貢獻。)
asynchat, asyncore, smtpd¶
自 Python 3.6 起,這些模組在其文件中被標記為已棄用。引入時的 DeprecationWarning
現已新增到這三個模組中。
base64¶
新增 base64.b32hexencode()
和 base64.b32hexdecode()
以支援擴充十六進位字母的 Base32 編碼 (Base32 Encoding with Extended Hex Alphabet)。
bdb¶
新增 clearBreakpoints()
來重置所有設定的斷點。(由 Irit Katriel 在 bpo-24160 中貢獻。)
bisect¶
新增向 bisect
模組 API 提供 key 函式的可能性。(由 Raymond Hettinger 在 bpo-4356 中貢獻。)
codecs¶
新增 codecs.unregister()
函式來取消註冊 (unregister) 一個編解碼器的搜索功能。 (Hai Shi在 bpo-41842 中貢獻。)
collections.abc¶
collections.abc.Callable
的參數化泛型 (parameterized generic) 的 __args__
現在與 typing.Callable
一致。collections.abc.Callable
泛型現在會將型別參數攤平,類似於 typing.Callable
目前的做法。這意味著 collections.abc.Callable[[int, str], str]
將具有 (int, str, str)
的 __args__
;在以前這是 ([int, str], str)
。為了允許此更改,現在可以對 types.GenericAlias
進行子類別化,並且在下標 (subscript) collections.abc.Callable
型別時將回傳子類別。請注意,對於無效形式的 collections.abc.Callable
參數化可能會引發 TypeError
,而在 Python 3.9 中該參數可能會無引發例外地傳遞。(由 Ken Jin 在 bpo-42195 中貢獻。)
contextlib¶
新增 contextlib.aclosing()
情境管理器以安全地關閉非同步產生器和表示非同步釋放資源的物件。(由 Joongi Kim 和 John Belmonte 在 bpo-41229 中貢獻。)
向 contextlib.nullcontext()
新增非同步情境管理器支援。(由 Tom Gringauz 在 bpo-41543 中貢獻。)
新增 AsyncContextDecorator
,用於支援將非同步情境管理器作為裝飾器使用。
curses¶
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 在 bpo-36982 中貢獻。)
如果 BUTTON5_*
常數是由底層 curses
函式庫提供的,那麼它們現在會在 curses 模組中公開。(由 Zackery Spytz 在 bpo-39273 中貢獻。)
dataclasses¶
__slots__¶
在 dataclasses.dataclass()
裝飾器中新增了 slots
參數。(由 Yurii Karabas 在 bpo-42269 中貢獻)
僅限關鍵字欄位 (Keyword-only fields)¶
dataclasses 現在支援在產生的 __init__ 方法中包含僅限關鍵字的欄位。有多種方法可以指定僅限關鍵字欄位。
你可以說每個欄位都是關鍵字:
from dataclasses import dataclass
@dataclass(kw_only=True)
class Birthday:
name: str
birthday: datetime.date
name
和 birthday
都是產生的 __init__ 方法的僅限關鍵字參數。
你可以在每個欄位的基礎上指定僅限關鍵字:
from dataclasses import dataclass, field
@dataclass
class Birthday:
name: str
birthday: datetime.date = field(kw_only=True)
這裡只有 birthday
是僅限關鍵字。如果你在各個欄位上設定 kw_only
,請注意,由於僅限關鍵字欄位需要遵循非僅限關鍵字欄位,因此會有欄位重新排序的相關規則。詳細資訊請參閱完整的 dataclasses 文件。
你還可以指定 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
則不是。(由 Eric V. Smith 在 bpo-43532 中貢獻。)
distutils¶
整個 distutils
套件已被棄用,將在 Python 3.12 中刪除。它指定套件建置的功能已經完全被第三方套件 setuptools
和 packaging
所取代,並且大多數其他常用的 API 都可以在標準函式庫的其他地方被找到(例如 platform
、shutil
、subprocess
或 sysconfig
)。目前沒有將 distutils
遷移任何其他地方的計畫,且使用其他功能的應用程式應該開始規劃如何取得程式碼的私有副本。請參閱 PEP 632 的討論。
Python 3.8 中不推薦使用的 bdist_wininst
命令已被刪除。現在建議使用 bdist_wheel
命令來在 Windows 上發布二進位套件。(由 Victor Stinner 在 bpo-42802 中貢獻。)
doctest¶
當模組未定義 __loader__
時,回退到 __spec__.loader
。(由 Brett Cannon 在 bpo-42133 中貢獻。)
encodings¶
encodings.normalize_encoding()
現在會忽略非 ASCII 字元。(Hai Shi 在 bpo-39337 中貢獻。)
enum¶
Enum
__repr__()
現在會回傳 enum_name.member_name
、__str__()
現在會回傳 member_name
。可用作模組常數的標準函式庫列舉會有 module_name.member_name
的 repr()
。(由 Ethan Furman 在 bpo-40066 中貢獻。)
新增 enum.StrEnum
,為所有成員都是字串的列舉。(由 Ethan Furman 在 bpo-41816 中貢獻。)
fileinput¶
在 fileinput.input()
和 fileinput.FileInput
中新增 encoding 和 errors 參數。(由 Inada Naoki 在 bpo-43712 中貢獻。)
當 mode 為 "r" 並且檔案有被壓縮時,fileinput.hook_compressed()
現在會回傳 TextIOWrapper
物件(和未壓縮檔案一樣)。(由 Inada Naoki 在 bpo-5758 中貢獻。)
faulthandler¶
faulthandler
模組現在可以檢測垃圾收集器 (garbage collector) 在收集期間是否發生嚴重錯誤。(由 Victor Stinner 在 bpo-44466 中貢獻。)
gc¶
為 gc.get_objects()
、gc.get_referrers()
和 gc.get_referents()
新增稽核掛鉤 (audit hooks)。(由 Pablo Galindo 在 bpo-43439 中貢獻。)
glob¶
在 glob()
和 iglob()
中新增 root_dir 和 dir_fd 參數,允許指定搜索的根目錄。(由 Serhiy Storchaka 在 bpo-38144 中貢獻。)
hashlib¶
hashlib 模組需要 OpenSSL 1.1.1 或更高版本。(由 Christian Heimes 在 PEP 644 和 bpo-43669 中貢獻。)
hashlib 模組初步支援 OpenSSL 3.0.0。(由 Christian Heimes 在 bpo-38820 和其他問題中貢獻。)
純 Python 的 pbkdf2_hmac()
回退已被棄用。將來只有在有 OpenSSL 支援的建置 Python 中才能夠使用 PBKDF2-HMAC。(由 Christian Heimes 在 bpo-43880 中貢獻。)
hmac¶
hmac 模組現在在內部使用 OpenSSL 的 HMAC 實作。 (由 Christian Heimes 在 bpo-40645 中貢獻。)
IDLE 和 idlelib¶
讓 IDLE 調用 sys.excepthook()
(在沒有 -n
的情況下啟動時)。使用者掛鉤 (user hooks) 在以前是被忽略的。(由 Ken Hilton 在 bpo-43008 中貢獻。)
重新排列設定對話框。將 General 分頁拆分為 Windows 和 Shell/Ed 分頁。將擴充 Help 選單的幫助來源移至 Extensions 分頁。為新選項騰出空間並縮短對話框,而後者使對話框更好地適應較小的螢幕。(由 Terry Jan Reedy 在 bpo-40468 中貢獻。)將縮排空間設定從 Font 分頁移至新的 Windows 分頁。(由 Mark Roseman 和 Terry Jan Reedy 在 bpo-33962 中貢獻。)
上述更改已向後移植到 3.9 維護版本。
新增 Shell 側邊欄。將主要提示字元 (>>>
) 移至側邊欄。將輔助提示字元(...
)新增到側邊欄。點擊左鍵再拖動能夠選擇一行或多行文字,和編輯器列號側邊欄操作一樣。選擇文字列後點擊右鍵會顯示帶有「一併複製提示字元 (copy with prompts)」的情境選單,這會將側邊欄中提示字元與所選文字並排,此選項也會出現在文字的情境選單上。(由 Tal Einat 在 bpo-37903 中貢獻。)
使用空格而不是製表符號 (tab) 來縮進交互式程式碼。這能夠使交互式程式碼條目「看起來正確」。新增 shell 側邊欄的主要動機是實現這一點。(由 Terry Jan Reedy 在 bpo-37892 中貢獻。)
突顯 (highlight) 模式匹配陳述式中的新軟關鍵字 (soft keywords) match
、case
和 _
。然而這種突顯並不完美,並且在某些罕見的情況下會出錯,包括 case
模式中的一些 _
。(由 Tal Einat 在 bpo-44010 中貢獻。)
3.10 維護版本中的新增功能。
將語法突顯 (syntax highlighting) 應用於 .pyi
檔案。(由 Alex Waygood 和 Terry Jan Reedy 在 bpo-45447 中貢獻。)
保存帶有輸入和輸出的 Shell 時,會包含提示字元。(由 Terry Jan Reedy 在 gh-95191 中貢獻。)
importlib.metadata¶
與 importlib_metadata
4.6 功能相同(歷史)。
importlib.metadata 入口點現在透過新的 importlib.metadata.EntryPoints
類別提供了以群組和名稱選擇入口點的更好體驗。有關棄用與用法的更多資訊,請參閱文件中的相容性說明。
新增了 importlib.metadata.packages_distributions()
用於將頂階 Python 模組和套件解析出 importlib.metadata.Distribution
。
inspect¶
當模組未定義 __loader__
時,回退到 __spec__.loader
。(由 Brett Cannon 在 bpo-42133 中貢獻。)
新增 inspect.get_annotations()
,它可以安全地計算物件上定義的註釋。它是存取各種型別物件註釋的怪作法 (quirks) 的變通解法 (work around),並且對其檢查的物件做出很少的假設。 inspect.get_annotations()
也可以正確地取消字串化註釋 (stringized 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 在 bpo-43817 中貢獻。)
itertools¶
新增 itertools.pairwise()
。(由 Raymond Hettinger 在 bpo-38200 中貢獻。)
linecache¶
當模組未定義 __loader__
時,回退到 __spec__.loader
。(由 Brett Cannon 在 bpo-42133 中貢獻。)
os¶
為 VxWorks RTOS 新增 os.cpu_count()
支援。(由 Peixing Xin 在 bpo-41440 中貢獻。)
新增函式 os.eventfd()
和相關幫助程式來包裝 Linux 上的 eventfd2
系統呼叫。 (由 Christian Heimes 在 bpo-41001 中貢獻。)
新增 os.splice()
以允許在兩個檔案描述器 (file descriptor) 之間移動資料,而無需在核心地址空間 (kernel address space) 和使用者地址空間 (user address space) 之間進行複製,其中檔案描述器之一必須是個 pipe。(由 Pablo Galindo 在 bpo-41625 中貢獻。)
为 macOS 增加了 O_EVTONLY
, O_FSYNC
, O_SYMLINK
和 O_NOFOLLOW_ANY
。 (由 Donghee Na 在 bpo-43106 中贡献。)
os.path¶
os.path.realpath()
現在接受一個 strict 僅限關鍵字引數。當設定為 True
時,如果路徑不存在或遇到符號鏈接循環 (symlink loop),則會引發 OSError
。(由 Barney Gale 在 bpo-43757 中貢獻。)
pathlib¶
新增 PurePath.parents
對於切片的支援。 (由 Joshua Cannon 在 bpo-35498 中貢獻。)
向 PurePath.parents
新增負索引支援。(由 Yaroslav Pankovych 在 bpo-21041 中貢獻。)
新增替代 link_to()
的 Path.hardlink_to
方法。新方法與 symlink_to()
具有相同的引數順序。(由 Barney Gale 在 bpo-39950 中貢獻。)
pathlib.Path.stat()
和 chmod()
現在接受 follow_symlinks 僅限關鍵字引數,以與 os
模組中的相應函式保持一致。(由 Barney Gale 在 bpo-39906 中貢獻。)
platform¶
新增 platform.freedesktop_os_release()
以從 freedesktop.org os-release 標準檔案中檢索出作業系統標識。 (由 Christian Heimes 在 bpo-28468 中貢獻。)
pprint¶
pprint.pprint()
現在接受新的 underscore_numbers
關鍵字引數。(由 sblondon 在 bpo-42914 中貢獻。)
pprint
現在可以漂亮地印出 dataclasses.dataclass
實例。(由 Lewis Gaul 在 bpo-43080 中貢獻。)
py_compile¶
將 --quiet
選項新增到 py_compile
的命令列界面。(由 Gregory Schevchenko 在 bpo-38731 中貢獻。)
pyclbr¶
在 pyclbr.readmodule()
和 pyclbr.readmodule_ex()
返回的结果树中的 Function
和 Class
对象上添加一个 end_lineno
属性。 它将匹配现有的 (起始) lineno
。 (由 Aviral Srivastava 在 bpo-38307 中贡献。)
shelve¶
现在 shelve
在创建 shelve 时默认使用 pickle.DEFAULT_PROTOCOL
而不是 pickle
协议 3
。 (由 Zackery Spytz 在 bpo-34204 中贡献。)
statistics¶
新增 covariance()
、Pearson correlation()
和簡單 linear_regression()
函式。(由 Tymoteusz Wołodźko 在 bpo-38490 中貢獻。)
site¶
當模組未定義 __loader__
時,回退到 __spec__.loader
。(由 Brett Cannon 在 bpo-42133 中貢獻。)
socket¶
socket.timeout
例外現在是 TimeoutError
的別名。(由 Christian Heimes 在 bpo-42413 中貢獻。)
新增使用 IPPROTO_MPTCP
建立 MPTCP socket 的選項(由 Rui Cunha 在 bpo-43571 中貢獻。)
新增 IP_RECVTOS
選項以接收服務型別 (type of service, ToS) 或 DSCP/ECN 欄位(由 Georg Sauthoff 在 44077 中貢獻。)
ssl¶
ssl 模組需要 OpenSSL 1.1.1 或更高版本。(由 Christian Heimes 在 PEP 644 和 bpo-43669 中貢獻。)
ssl 模块已初步支持 OpenSSL 3.0.0 和新选项 OP_IGNORE_UNEXPECTED_EOF
。 (由 Christian Heimes 在 bpo-38820, bpo-43794, bpo-43788, bpo-43791, bpo-43799, bpo-43920, bpo-43789 和 bpo-43811 中贡献。)
已棄用函式和使用已棄用常數現在會導致 DeprecationWarning
。 ssl.SSLContext.options
預設設定有 OP_NO_SSLv2
和 OP_NO_SSLv3
,因此無法再次發出設定該旗標的警告。棄用部分包含已棄用功能的列表。(由 Christian Heimes 在 bpo-43880 中貢獻。)
ssl 模組現在具有更安全的預設設定。預設情況下禁用沒有前向保密或 SHA-1 MAC 的密碼。安全級別 2 禁止安全性低於 112 位元的弱 RSA、DH 和 ECC 密鑰。 SSLContext
預設為最低協議版本 TLS 1.2。設定基於 Hynek Schlawack 的研究。 (由 Christian Heimes 在 bpo-43998 中貢獻。)
不再正式支援已棄用的協議 SSL 3.0、TLS 1.0 和 TLS 1.1。 Python 不會主動阻止它們。然而,OpenSSL 建置選項、發行版配置、發行商補丁和密碼套件可能會阻止交握的成功。
向 ssl.get_server_certificate()
函式新增 timeout 參數。(由 Zackery Spytz 在 bpo-31870 中貢獻。)
ssl 模組使用堆疊類型 (heap-types) 和多階段初始化 (multi-phase initialization)。(由 Christian Heimes 在 bpo-42333 中貢獻。)
增加了一个新的校验旗标 VERIFY_X509_PARTIAL_CHAIN
。 (由 l0x 在 bpo-40849 中贡献。)
sqlite3¶
新增 connect/handle()
、enable_load_extension()
和 load_extension()
的稽核事件。(由 Erlend E. Aasland 在 bpo-43762 中貢獻。)
sys¶
新增 sys.orig_argv
屬性:傳遞給 Python 可執行檔案的原始命令列引數列表。(由 Victor Stinner 在 bpo-23427 中貢獻。)
新增 sys.stdlib_module_names
,其中包含標準函式庫模組的名稱列表。 (由 Victor Stinner 在 bpo-42955 中貢獻。)
_thread¶
现在 _thread.interrupt_main()
接受一个可选的信号数值供模拟 (默认值仍为 signal.SIGINT
)。 (由 Antoine Pitrou 在 bpo-43356 中贡献。)
threading¶
新增 threading.gettrace()
和 threading.getprofile()
分別取得 threading.settrace()
和 threading.setprofile()
設定的函式。(由 Mario Corchero 在 bpo-42251 中貢獻。)
新增 threading.__excepthook__
以允許取得 threading.excepthook()
的原始值,以防它被設定為損壞或不同的值。(由 Mario Corchero 在 bpo-42308 中貢獻。)
traceback¶
format_exception()
、format_exception_only()
和 print_exception()
函式現在可以將例外物件作為僅限位置引數。(由 Zackery Spytz 和 Matthias Bussonnier 在 bpo-26389 中貢獻。)
types¶
重新引入 types.EllipsisType
、types.NoneType
和 types.NotImplementedType
類別,提供一組易於型別檢查器直譯的新型別。(由 Bas van Beek 在 bpo-41810 中貢獻。)
typing¶
有關重大更改,請參閱與型別提示相關的新功能。
typing.Literal
的行為已更改為符合 PEP 586 並匹配 PEP 中指定的靜態型別檢查器的行為。
Literal
現在可以刪除重複參數。Literal
物件之間的相等性比較現在與順序無關。現在型別的比較會優先於
Literal
的比較。例如,Literal[0] == Literal[False]
先前之求值為True
,但現在它是False
。為了支援此更改,內部使用的型別快取現在支援了型別的辨認。如果
Literal
物件的任ㄧ參數不是可雜湊的,那麼它們現在將在相等性比較期間引發TypeError
例外。請注意,使用不可雜湊的參數宣告Literal
不會引發錯誤:>>> from typing import Literal >>> Literal[{0}] >>> Literal[{0}] == Literal[{False}] Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: unhashable type: 'set'
(由 Yurii Karabas 在 bpo-42345 中貢獻。)
新增函式 typing.is_typeddict()
來自我審查 (introspect) 註釋是否為 typing.TypedDict
。(由 Patrick Reader 在 bpo-41792 中貢獻。)
僅宣告了資料變數的 typing.Protocol
子類別現在在使用 isinstance
檢查時會引發 TypeError
,除非它們用 runtime_checkable()
裝飾。此前,這些檢查都是悄無聲息地通過的。如果使用者需要執行環境協議 (runtime protocol),則應該使用 runtime_checkable()
裝飾器來裝飾其子類別。(由 Yurii Karabas 在 bpo-38908 中貢獻。)
從 typing.io
和 typing.re
子模組引入現在將發出 DeprecationWarning
。這些子模組自 Python 3.8 起已被棄用,並將在未來版本的 Python 中刪除。屬於這些子模組的任何內容都應該直接從 typing
引入。 (由 Sebastian Rittau 在 bpo-38291 中貢獻。)
unittest¶
新增方法 assertNoLogs()
以補足現有的 assertLogs()
。(由 Kit Yan Choi 在 bpo-39385 中貢獻。)
urllib.parse¶
Python 3.10 之前的 Python 版本允許在 urllib.parse.parse_qs()
和 urllib.parse.parse_qsl()
中使用 ;
和 &
作為查詢參數 (query parameter) 的分隔符號。出於安全考慮,並且為了符合更新的 W3C 建議,已將其更改為僅允許單個分隔符號鍵,預設為 &
。此更改還會影響 cgi.parse()
和 cgi.parse_multipart()
,因為它們在內部使用受影響的函式。有關更多詳細資訊,請參閱各自的文件。(由 Adam Goldschmidt、Senthil Kumaran 和 Ken Jin 在 bpo-42967 中貢獻。)
在 URL 中存在换行符或制表符可能会导致某种形式的攻击。 根据更新了 RFC 3986 的 WHATWG 规范,urllib.parse
中的解析器将从 URL 中去除 ASCII 换行符 \n
, \r
和制表符 \t
以防止这种攻击。 移除的字符将由一个新的模块层级变量 urllib.parse._UNSAFE_URL_BYTES_TO_REMOVE
来控制。 (参见 gh-88048。)
xml¶
新增 LexicalHandler
類別到 xml.sax.handler
模組。(由 Jonathan Gossage 和 Zackery Spytz 在 bpo-35018 中貢獻。)
zipimport¶
新增與 PEP 451 相關的方法:find_spec()
、zipimport.zipimporter.create_module()
和 zipimport.zipimporter.exec_module()
。(由 Brett Cannon 在 bpo-42131 中貢獻。)
新增 invalidate_caches()
方法。(由 Desmond Cheong 在 bpo-14678 中貢獻。)
最佳化¶
建構函式
str()
、bytes()
和bytearray()
現在更快了(對於小型物件大約快了 30--40%)。(由 Serhiy Storchaka 在 bpo-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 在 bpo-41006 和 bpo-41718 中貢獻。)LOAD_ATTR
指令現在使用新的「操作碼快取 (per opcode cache)」機制。現在一般屬性的速度提高了約 36%,槽位 (slot) 的速度提高了 44%。(由 Pablo Galindo 和 Yury Selivanov 在 bpo-42093 中以及 Guido van Rossum 在 bpo-42927 中貢獻,基於最初在 PyPy 和 MicroPython 中實作的想法。)當使用
--enable-optimizations
建置 Python 時,現在-fno-semantic-interposition
被新增到編譯和鏈接列 (link line) 中。這使得使用--enable-shared
和gcc
建立的 Python 直譯器的建置速度提高了 30%。請參閱本文 以了解詳情。(由 Victor Stinner 和 Pablo Galindo 在 bpo-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 於 bpo-41486 貢獻、由 Gregory P. Smith 審閱)使用字串化註釋時,建立函式時不再建立函式的註釋字典。取而代之的是它們被存儲為字串元組,且函式物件會根據需求才將其延遲轉換 (lazily convert) 為註釋字典。此最佳化將定義帶有註釋的函式所需的 CPU 時間減少了一半。(由 Yurii Karabas 和 Inada Naoki 在 bpo-42202 中貢獻。)
像是
str1 in str2
和str2.find(str1)
之類的子字串搜索函式現在有時會使用 Crochemore & Perrin 的「雙向」字串搜索演算法來避免作用於長字串上時發生二次方行為 (quadratic behavior)。(由 Dennis Sweeney 在 bpo-41972 中貢獻)向
_PyType_Lookup()
新增微最佳化以提高快取命中的常見情況下的型別屬性快取查找性能。這使得直譯器平均速度提高了 1.04 倍。(由 Dino Viehland 在 bpo-43452 中貢獻。)下列内置函数现在支持更快速的 PEP 590 vectorcall 调用约定:
map()
,filter()
,reversed()
,bool()
和float()
。 (由 Donghee Na 和 Jeroen Demeyer 在 bpo-43575, bpo-43287, bpo-41922, bpo-41873 和 bpo-41870 中贡献。)通過刪除內部
RLock
,BZ2File
的性能得到了改進。這使得BZ2File
在面對多個同時的讀取器或寫入器時執行緒不安全,就像gzip
和lzma
中的等效類別一樣。(由 Inada Naoki 在 bpo-43785 中貢獻。)
已棄用¶
目前 Python 接受緊跟關鍵字的數字字面值 (numeric literals),例如
0in x
、1or x
、0if 1else 2
。它允許了令人困惑和不明確的運算式,例如[0x1for x in y]
(可以直譯為[0x1 for x in y]
或[0x1f or x in y]
)。從此版本開始,如果數字字面值後緊跟關鍵字and
、else
、for
、if
、in
、is
與or
其中之一,則會引發棄用警告。在未來的版本中,它將被變更為語法警告,最後成為為語法錯誤。(由 Serhiy Storchaka 在 bpo-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 在 bpo-37319 中貢獻。)importlib
的各種load_module()
方法自 Python 3.6 起已被記錄為已棄用,但現在也會觸發DeprecationWarning
。請改用exec_module()
。(由 Brett Cannon 在 bpo-26131 中貢獻。)zimport.zipimporter.load_module()
已被棄用,請用exec_module()
。(由 Brett Cannon 在 bpo-26131 中貢獻。)引入系統使用
load_module()
現在會觸發ImportWarning
,因為exec_module()
是當前首選。(由 Brett Cannon 在 bpo-26131 中貢獻。)引入系統使用
importlib.abc.MetaPathFinder.find_module()
和importlib.abc.PathEntryFinder.find_module()
現在會觸發ImportWarning
作為importlib.abc.MetaPathFinder.find_spec()
和importlib.abc.PathEntryFinder.find_spec()
分別是首選。你可以使用importlib.util.spec_from_loader()
來幫助移植。(由 Brett Cannon 在 bpo-42134 中貢獻。)引入系統使用
importlib.abc.PathEntryFinder.find_loader()
現在會觸發ImportWarning
,因為importlib.abc.PathEntryFinder.find_spec()
是首選。你可以使用importlib.util.spec_from_loader()
來幫助移植。(由 Brett Cannon 在 bpo-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 在 bpo-42135 中貢獻。)importlib.abc.Finder
已被棄用(包括其唯一方法find_module()
)。importlib.abc.MetaPathFinder
和importlib.abc.PathEntryFinder
都不再從該類別繼承。使用者應該根據需求來選擇其一以繼承。 (由 Brett Cannon 在 bpo-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 列為預定的刪除版本(它們開始在過去版本的 Python 中引發DeprecationWarning
) 。(由 Brett Cannon 在 bpo-43720 中貢獻。)引入系統現在在模組上使用
__spec__
屬性,然後才會回退使用module_repr()
作為模組的__repr__()
方法。計劃在 Python 3.12 中刪除module_repr()
的使用。(由 Brett Cannon 在 bpo-42137 中貢獻。)importlib.abc.Loader.module_repr()
、importlib.machinery.FrozenLoader.module_repr()
和importlib.machinery.BuiltinLoader.module_repr()
已棄用並計劃在 Python 3.12 中刪除。(由 Brett Cannon 在 bpo-42136 中貢獻。)自 Python 3.3 起,
sqlite3.OptimizedUnicode
就沒有文件記錄並且已過時,當時它被用作str
的別名。它現已被棄用,並計劃在 Python 3.12 中刪除。(由 Erlend E. Aasland 在 bpo-42264 中貢獻。)未記錄於說明文件的內建函式
sqlite3.enable_shared_cache
現已棄用,計劃在 Python 3.12 中刪除。SQLite3 文件強烈建議不去使用它。有關更多詳細資訊,請參閱 SQLite3 文件。如果必須使用共享快取,請使用cache=shared
查詢參數以 URI 模式打開資料庫。(由 Erlend E. Aasland 在 bpo-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.name
threading.thread.getName
=>threading.Thread.name
threading.Thread.isDaemon
=>threading.Thread.daemon
threading.Thread.setDaemon
=>threading.Thread.daemon
(由 Jelle Zijlstra 在 gh-87889 中貢獻。)
pathlib.Path.link_to()
已棄用並計劃在 Python 3.12 中刪除。請改用pathlib.Path.hardlink_to()
。(由 Barney Gale 在 bpo-39950 中貢獻。)cgi.log()
已棄用並計劃在 Python 3.12 中刪除。(由 Inada Naoki 在 bpo-41139 中貢獻。)自 Python 3.6、Python 3.7 或 OpenSSL 1.1.0 起,以下
ssl
功能已被棄用,並將在 3.11 中刪除:OP_NO_SSLv2
、OP_NO_SSLv3
、OP_NO_TLSv1
、OP_NO_TLSv1_1
、OP_NO_TLSv1_2
、和OP_NO_TLSv1_3
已被替換為sslSSLContext.minimum_version
和sslSSLContext.maximum_version
。PROTOCOL_SSLv2
,PROTOCOL_SSLv3
,PROTOCOL_SSLv23
,PROTOCOL_TLSv1
,PROTOCOL_TLSv1_1
,PROTOCOL_TLSv1_2
和PROTOCOL_TLS
已被弃用并应改用PROTOCOL_TLS_CLIENT
和PROTOCOL_TLS_SERVER
RAND_pseudo_bytes()
,RAND_egd()
NPN 功能如
ssl.SSLSocket.selected_npn_protocol()
和ssl.SSLContext.set_npn_protocols()
已被 ALPN 取代。
執行緒除錯(
PYTHONTHREADDEBUG
環境變數)在 Python 3.10 中已棄用,並將在 Python 3.12 中刪除。此功能需要一個 Python 的除錯用建置版本。(由 Victor Stinner 在 bpo-44584 中貢獻。)從
typing.io
和typing.re
子模組引入現在將發出DeprecationWarning
。這些子模組將在 Python 的未來版本中刪除。屬於這些子模組的任何內容都應該直接從typing
引入。(由 Sebastian Rittau 在 bpo-38291 中貢獻。)
已刪除¶
刪除了
complex
類別的特殊方法__int__
、__float__
、__floordiv__
、__mod__
、__divmod__
、__rfloordiv__
、__rmod__
和__rdivmod__
。它們都會引發TypeError
。(由 Serhiy Storchaka 在 bpo-41974 中貢獻。)_markupbase
模組中私有、未於文件記錄的ParserBase.error()
方法已被刪除。html.parser.HTMLParser
是ParserBase
的唯一子類別,它的error()
實作已在 Python 3.5 中刪除。(由 Berker Peksag 在 bpo-31844 中貢獻。)刪除了
unicodedata.ucnhash_CAPI
屬性,該屬性是內部 PyCapsule 物件。相關的私有_PyUnicode_Name_CAPI
結構已移至內部 C API。(由 Victor Stinner 在 bpo-42157 中貢獻。)刪除了由於切換到新的 PEG 剖析器而在 3.9 中被棄用的
parser
模組。僅由舊剖析器使用的所有 C 原始碼和標頭檔也已被刪除,包括node.h
、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 生命期结束之后。 现有用户应当将它们用到的所有类都拷贝到自己的代码中。 (由 Donghee Na 和 Terry J. Reedy 在 bpo-42299 中贡献。)移除了
PyModule_GetWarningsModule()
函数,现在被由于_warnings
模块在 2.6 中被转换为内置模块而变得没有用处。 (由 Hai Shi 在 bpo-42599 中贡献。)從
collections
模組中刪除已棄用的、對 容器抽象基类 的別名。(由 Victor Stinner 在 bpo-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 在 bpo-42392 中貢獻。)
移植到 Python 3.10¶
本節列出了前面描述的更改以及可能需要更改程式碼的其他錯誤修復。
Python 語法的變化¶
如果數字字面值後面緊跟關鍵字(如
0in x
),在以前是有效的語法,但現在在編譯時會發出棄用警告。在未來的版本中,它將更改為語法警告,最後更改為語法錯誤。要消除警告並使程式碼與未來版本相容,只需在數字字面值和以下關鍵字之間新增一個空格即可。(由 Serhiy Storchaka 在 bpo-43833 中貢獻。)
Python API 的變化¶
format_exception()
、format_exception_only()
和traceback
模組中的print_exception()
函式的 etype 參數已重命名為 exc。(由 Zackery Spytz 和 Matthias Bussonnier 在 bpo-26389 中貢獻。)atexit
:在 Python 退出時,如果一個使用atexit.register()
註冊的回呼 (callback) 失敗,該例外現在會被記錄下來。在以前只記錄一些例外,並且最後一個例外總是被默默地忽略。(由 Victor Stinner 在 bpo-42639 中貢獻。)collections.abc.Callable
泛型現在會攤平型別參數,類似於typing.Callable
目前的做法。這意味著collections.abc.Callable[[int, str], str]
將具有(int, str, str)
的__args__
;以前這是([int, str], str)
。透過typing.get_args()
或__args__
存取參數的程式碼需要考慮此變更。此外,對於無效形式的參數化collections.abc.Callable
,可能會引發TypeError
,而在 Python 3.9 中,該參數可能已被默默地傳遞。(由 Ken Jin 在 bpo-42195 中貢獻。)如果給定參數不適合 16 位元無符號整數 (16-bit unsigned integer),
socket.htons()
和socket.ntohs()
現在會引發OverflowError
而不是DeprecationWarning
。(由 Erlend E. Aasland 在 bpo-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()
被專門設計為 不 在當前執行緒的事件循環中運行(例如在另一個執行緒的事件循環中運行),請考慮改用asyncio.run_coroutine_threadsafe()
。(由 Yurii Karabas、Andrew Svetlov、Yury Selivanov 和 Kyle Stanley 在 bpo-42392 中貢獻。)
如果 globals 字典沒有
"__builtins__"
鍵,則types.FunctionType
建構函式現在會繼承當前的內建物件,而不是使用{"None": None}
:相同行為如eval()
和exec()
函式。在 Python 中使用def function(...): ...
定義函式不受影響,全域變數不能用此語法覆蓋:它也繼承當前的內建物件。 (由 Victor Stinner 在 bpo-42990 中貢獻。)
C API 中的改動¶
由於切換到新的 PEG 剖析器,C API 函式
PyParser_SimpleParseStringFlags
、PyParser_SimpleParseStringFlagsFilename
、PyParser_SimpleParseFileFlags
、PyNode_Compile
和被這些函式使用的型別struct _node
被刪除。現在應該將源程式碼直接(例如透過
Py_CompileString()
)編譯為程式碼物件。然後可以(例如透過PyEval_EvalCode()
)為產生的程式碼物件求值 (evaluated)。具體來說:
後跟有
PyNode_Compile
呼叫的PyParser_SimpleParseStringFlags
呼叫,可以替換為呼叫Py_CompileString()
。沒有
PyParser_SimpleParseFileFlags
的直接替代品。要從FILE *
引數編譯程式碼,你需要用 C 讀取檔案並將結果緩衝區傳遞給Py_CompileString()
。要編譯給定
char *
檔案名稱的檔案,請顯式打開該檔案,讀取它並編譯結果。一種方法是使用io
模組和PyImport_ImportModule()
、PyObject_CallMethod()
、PyBytes_AsString()
和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
指令現在接受字典或字串元組作為函式的註釋。(由 Yurii Karabas 和 Inada Naoki 在 bpo-42202 中貢獻。)
建置變更¶
PEP 644:Python 現在需要 OpenSSL 1.1.1 或更高版本。不再支援 OpenSSL 1.0.2。(由 Christian Heimes 在 bpo-43669 中貢獻。)
現在需要 C99 函式
snprintf()
和vsnprintf()
來建置 Python。 (由 Victor Stinner 在 bpo-36020 中貢獻。)sqlite3
需要 SQLite 3.7.15 或更新版本。(由 Sergey Fedoseev 和 Erlend E. Aasland 在 bpo-40744 和 bpo-40810 中貢獻。)將
--disable-test-modules
選項新增到configure
腳本中:不建置也不安裝測試模組。(由 Xavier de Gaye、Thomas Petazzoni 和 Peixing Xin 在 bpo-27640 中貢獻。)將
--with-wheel-pkg-dir=PATH 選項
新增到./configure
腳本中。如果有指定,ensurepip
模組會在此目錄中查找setuptools
和pip
wheel 套件:如果兩者都存在,則使用這些 wheel 套件而不是 ensurepip 捆綁的 wheel 套件。一些 Linux 發行版的打包策略建議不要一併包入依賴項目。例如,Fedora 在
/usr/share/python-wheels/
目錄中安裝 wheel 套件,並且不安裝ensurepip._bundled
套件。(由 Victor Stinner 在 bpo-42856 中貢獻。)
新增
configure --without-static-libpython 選項
以不建置libpythonMAJOR.MINOR.a
靜態函式庫且不安裝python.o
目標檔案。(由 Victor Stinner 在 bpo-43103 中貢獻。)
如果可用,
configure
腳本現在使用pkg-config
工具程式 (utility) 來檢測 Tcl/Tk 標頭檔和函式庫的位置。和以前一樣,可以使用--with-tcltk-includes
和--with-tcltk-libs
配置選項顯式指定這些位置。(由 Manolis Stamatogiannakis 在 bpo-42603 中貢獻。)將
--with-openssl-rpath
選項新增到configure
腳本中。該選項簡化了使用自定義 OpenSSL 安裝建置 Python 的過程,例如./configure --with-openssl=/path/to/openssl --with-openssl-rpath=auto
。(由 Christian Heimes 在 bpo-43466 中貢獻。)
C API 變更¶
PEP 652:維護穩定 ABI¶
用於擴充模組或嵌入 Python 的穩定 ABI(應用程式二進位介面)現已明確定義。 C API 穩定性 描述了 C API 和 ABI 穩定性保證以及使用穩定 ABI 的最佳實踐。
新功能¶
PyNumber_Index()
的結果現在都具有精確的int
型別。在以前,結果可能是int
子類別的實例。(由 Serhiy Storchaka 在 bpo-40792 中貢獻。)將新的
orig_argv
成員新增到PyConfig
結構:傳遞給 Python 可執行檔案的原始命令列參數列表。(由 Victor Stinner 在 bpo-23427 中貢獻。)新增了
PyDateTime_DATE_GET_TZINFO()
和PyDateTime_TIME_GET_TZINFO()
巨集,用於存取datetime.datetime
和datetime.time
物件的tzinfo
屬性。(由 Zackery Spytz 在 bpo-30155 中貢獻。)新增
PyCodec_Unregister()
函式來取消註冊編解碼器搜索函式。(由 Hai Shi 在 bpo-41842 中貢獻。)新增了
PyIter_Send()
函式,以允許將值發送到疊代器中,而不會引發StopIteration
例外。(由 Vladimir Matveev 在 bpo-41756 中貢獻。)將
PyUnicode_AsUTF8AndSize()
新增到受限 C API (limited C API) 中。(由 Alex Gaynor 在 bpo-41784 中貢獻。)新增
PyModule_AddObjectRef()
函式:類似於PyModule_AddObject()
但成功時不竊取對值的參照。(由 Victor Stinner 在 bpo-1635741 中貢獻。)新增
Py_NewRef()
和Py_XNewRef()
函式來增加物件的參照計數並回傳物件。 (由 Victor Stinner 在 bpo-42262 中貢獻。)PyType_FromSpecWithBases()
和PyType_FromModuleAndSpec()
函式現在接受單個類別作為 bases 引數。(由 Serhiy Storchaka 在 bpo-42423 中貢獻。)PyType_FromModuleAndSpec()
函式現在接受 NULLtp_doc
槽位。(由 Hai Shi在 bpo-41832 中貢獻。)PyType_GetSlot()
函式可以接受靜態型別 (static type)。(由 Hai Shi 和 Petr Viktorin 在 bpo-41073 中貢獻。)向 C-API 新增
PySet_CheckExact()
函式,以檢查物件是否是set
的實例而不是子型別的實例。(由 Pablo Galindo 在 bpo-43277 中貢獻。)新增
PyErr_SetInterruptEx()
,它允許傳遞信號編號來進行模擬。 (由 Antoine Pitrou 在 bpo-43356 中貢獻。)如 Python 是在除錯模式 (debug mode) 下建置的(如果有定義
Py_DEBUG
巨集),現在會支援受限 C API。在受限 C API 中,如果 Python 是在除錯模式下建置的,並且Py_LIMITED_API
巨集的目標是 Python 3.10 或更新版本,Py_INCREF()
和Py_DECREF()
函式現在的實作是不透明函式呼叫,而不是直接存取PyObject.ob_refcnt
成員。在除錯模式下支援受限 C API 成為可能,因為自 Python 3.8 以來,PyObject
結構在發布和除錯模式下是相同的(請參閱:issue:36465)。--with-trace-refs
特殊建置(Py_TRACE_REFS
巨集)仍不支援受限 C API。(由 Victor Stinner 在 bpo-43688 中貢獻。)新增
Py_Is(x, y)
函式來測試 x 物件是否為 y 物件,與 Python 中的x is y
相同。還新增Py_IsNone()
、Py_IsTrue()
、Py_IsFalse()
函式來分別測試物件是否為None
單例、True
單例或False
單例。(由 Victor Stinner 在 bpo-43753 中貢獻。)新增函式以從 C 程式碼控制垃圾收集器:
PyGC_Enable()
、PyGC_Disable()
、PyGC_IsEnabled()
。這些函式使得能夠從 C 程式碼啟用、停用和查詢垃圾收集器的狀態,而無需引入gc
模組。新增了
Py_TPFLAGS_DISALLOW_INSTANTIATION
类型旗标用于禁止创建类型实例。 (由 Victor Stinner 在 bpo-43916 中贡献。).)新增了
Py_TPFLAGS_IMMUTABLETYPE
类型旗标用于创建不可变类型对象:类型的属性不可被设置或删除。 (由 Victor Stinner 和 Erlend E. Aasland 在 bpo-43908 中贡献。)
移植到 Python 3.10¶
現在必須定義
PY_SSIZE_T_CLEAN
巨集以使用PyArg_ParseTuple()
和Py_BuildValue()
格式,這些格式使用#
:es#
,et#
、s#
、u#
、y#
、z#
、U#
和Z#
。請參閱 剖析引數與建置數值 和 PEP 353。(由 Victor Stinner 在 bpo-40943 中貢獻。)由於
Py_REFCNT()
更改為行內靜態函式 (inline static function),因此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 在 bpo-39573 中貢獻。)
由於過去的種種原因,過去在不持有 GIL 的情況下呼叫
PyDict_GetItem()
是被允許的。目前已被禁止。(由 Victor Stinner 在 bpo-40839 中貢獻。)PyUnicode_FromUnicode(NULL, size)
和PyUnicode_FromStringAndSize(NULL, size)
現在會引發DeprecationWarning
。請改用PyUnicode_New()
來分配沒有初始資料的 Unicode 物件。(由 Inada Naoki 在 bpo-36346 中貢獻。)PyCapsule API
unicodedata.ucnhash_CAPI
的私有_PyUnicode_Name_CAPI
結構已移至內部 C API。(由 Victor Stinner 在 bpo-42157 中貢獻。)如果在
Py_Initialize()
之前(Python 初始化之前)被呼叫,Py_GetPath()
、Py_GetPrefix()
、Py_GetExecPrefix()
、Py_GetProgramFullPath()
、Py_GetPythonHome()
和Py_GetProgramName()
現在會回傳NULL
。使用新的 Python初始化配置 API 來獲取 Python 路径配置。(由 Victor Stinner 在 bpo-42260 中貢獻。)PyList_SET_ITEM()
、PyTuple_SET_ITEM()
和PyCell_SET()
巨集不能再用作左值 (l-value) 或右值 (r-value)。例如,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 在 bpo-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 在 bpo-35134 中貢獻。)请使用
Py_TPFLAGS_IMMUTABLETYPE
类型旗标来创建不可变类型对象。 请勿依赖于Py_TPFLAGS_HEAPTYPE
来确定类型对象是否可变;应改为检查是否设置了Py_TPFLAGS_IMMUTABLETYPE
。 (由 Victor Stinner 和 Erlend E. Aasland 在 bpo-43908 中贡献。)未以說明文件記錄的函式
Py_FrozenMain
已從受限 API 中刪除。該函式主要用於 Python 的自定義建置。(由 Petr Viktorin 在 bpo-26241 中貢獻。)
已棄用¶
PyUnicode_InternImmortal()
函式現已棄用,並將在 Python 3.12 中刪除:請改用PyUnicode_InternInPlace()
。(由 Victor Stinner 在 bpo-41692 中貢獻。)
已刪除¶
刪除了操作
Py_UNICODE*
字串的Py_UNICODE_str*
函式。(由 Inada Naoki 在 bpo-41123 中貢獻。)Py_UNICODE_strlen
:使用PyUnicode_GetLength()
或PyUnicode_GET_LENGTH
Py_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 在 bpo-41103 中貢獻。)刪除了
PyLong_FromUnicode()
。請改用PyLong_FromUnicodeObject()
。(由 Inada Naoki 在 bpo-41103 中貢獻。)刪除了
PyUnicode_AsUnicodeCopy()
。請改用PyUnicode_AsUCS4Copy()
或PyUnicode_AsWideCharString()
(由 Inada Naoki 在 bpo-41103 中貢獻。)刪除了
_Py_CheckRecursionLimit
變數:它已被PyInterpreterState
結構的ceval.recursion_limit
取代。(由 Victor Stinner 在 bpo-41834 中貢獻。)刪除了未被說明文件記錄的巨集
Py_ALLOW_RECURSION
和Py_END_ALLOW_RECURSION
以及PyInterpreterState
結構的recursion_ritic
欄位。(由 Serhiy Storchaka 在 bpo-41936 中貢獻。)刪除了未被說明文件記錄的
PyOS_InitInterrupts()
函式。初始化 Python 已經隱式安裝信號處理程式:請參閱PyConfig.install_signal_handlers
。(由 Victor Stinner 在 bpo-41713 中貢獻。)刪除
PyAST_Validate()
函式。不再可能使用公開 C API 來建置 AST 物件(mod_ty
類型)。該函式已被排除在受限 C API 之外 (PEP 384)。(由 Victor Stinner 在 bpo-43244 中貢獻。)刪除
symtable.h
標頭檔和未被說明文件記錄的函式:PyST_GetScope()
PySymtable_Build()
PySymtable_BuildObject()
PySymtable_Free()
Py_SymtableString()
Py_SymtableStringObject()
Py_SymtableString()
函式錯誤地成為穩定 ABI 的一部分,但它因為symtable.h
標頭檔被排除在受限 C API 之外而無法使用。從受限 C API 標頭和
python3.dll
(在 Windows 上提供穩定 ABI 的函式庫)中刪除PyOS_ReadlineFunctionPointer()
。由於該函式採用 FILE* 引數,因此無法保證其 ABI 穩定性。(由 Petr Viktorin 在 bpo-43868 中貢獻。)刪除
ast.h
、asdl.h
和Python-ast.h
標頭檔。這些函式沒有文件記錄,並且被排除在受限 C API 之外。這些標頭檔定義的大多數名稱都沒有前綴Py
,因此可能會產生名稱衝突。例如,Python-ast.h
定義了一個Yield
巨集,它與 Windows<winbase.h>
標頭使用的Yield
有名稱衝突。請改用 Pythonast
模組。(由 Victor Stinner 在 bpo-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 在 bpo-43244 中貢獻。)
刪除包含以下函式的
pyarena.h
標頭檔:PyArena_New()
PyArena_Free()
PyArena_Malloc()
PyArena_AddPyObject()
這些函式沒有文件記錄、被排除在受限 C API 之外,並僅被編譯器於內部使用。(由 Victor Stinner 在 bpo-43244 中貢獻。)
為了 Python 最佳化,已刪除
PyThreadState.use_tracing
成員。(由 Mark Shannon 在 bpo-43760 中貢獻。)
3.10.7 中的重要安全特性¶
使用十进制以外的底,如 2(二进制)、4、8(八进制)、16(十六进制)、32 以外作为基数在 int
和 str
之间进行转换,如果字符串形式的数字数量超过一个限制,会抛出 ValueError
,以避免因算法复杂而导致的潜在拒绝服务攻击。这是对 CVE-2020-10735 的缓解方案。这个限制可以通过环境变量、命令行旗标或 sys
API 进行配置或禁用。参见 integer string conversion length limitation 文档。默认限制是字符串形式的 4300 位数字。
3.10.8 中的重要安全特性¶
已被弃用的 mailcap
模块现在将拒绝将不安全的文本(文件名、MIME 类型、形参等)注入到 shell 命令中。 它不会使用此类文本,而是会发出警告并且将视作未找到匹配结果(或者对于测试命令,将视作测试失败)。 (由 Petr Viktorin 在 gh-98966 中贡献。)
3.10.12 中的重要变化¶
tarfile¶
tarfile
中的提取方法和shutil.unpack_archive()
都新增了 filter 参数以允许限制可能令人意外或危险的 tar 特性,例如在目标目录之外创建文件。 相关细节参见 解压缩过滤器。 在 Python 3.12 中,不带 filter 参数的用法将显示DeprecationWarning
。 在 Python 3.14 中,默认值将切换为'data'
。 (由 Petr Viktorin 在 PEP 706 中贡献。)