Python 3.10 有什么新變化?

發(fā)布版本

3.12.0a0

日期

五月 26, 2022

編者

Pablo Galindo Salgado

本文介紹了 Python 3.10 相比 3.9 的新增特性。

詳情請參閱 更新日志。

摘要 -- 發(fā)布重點?

新的語法特性:

  • PEP 634, 結構化模式匹配: 規(guī)范說明

  • PEP 635, 結構化模式匹配: 動機與理由

  • PEP 636, 結構化模式匹配: 教程

  • bpo-12782,加圓括號的上下文管理器現(xiàn)在正式被允許使用。

標準庫中的新特性:

  • PEP 618,向 zip 添加可選的長度檢查。

解釋器的改進:

  • PEP 626,在調(diào)試和其他工具中使用精確的行號。

新的類型標注特性:

  • PEP 604,允許 X | Y 形式的聯(lián)合類型寫法

  • PEP 613,顯式類型別名

  • PEP 612,形參規(guī)格變量

重要的棄用、移除或限制:

  • PEP 644,要求 OpenSSL 1.1.1 或更新的版本

  • PEP 632,棄用 distutils 模塊。

  • PEP 623,棄用并準備移除 PyUnicodeObject 中的 wstr 成員。

  • PEP 624,移除 Py_UNICODE 編碼器 API

  • PEP 597,增加可選的 EncodingWarning

新的特性?

帶圓括號的上下文管理器?

現(xiàn)在已支持使用外層圓括號來使多個上下文管理器可以連續(xù)多行地書寫。 這允許將過長的上下文管理器集能夠以與之前 import 語句類似的方式格式化為多行的形式。 例如,以下這些示例寫法現(xiàn)在都是有效的:

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 來了解更多細節(jié)。

(由 Guido van Rossum, Pablo Galindo 和 Lysandros Nikolaou 在 bpo-12782bpo-40334 中貢獻。)

更清楚的錯誤消息?

SyntaxError?

現(xiàn)在當解析包含有未關閉括號的代碼時解釋器會包括未關閉括號的位置而不是顯示 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 中則會發(fā)出信息量更多的錯誤提示:

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

類似地,涉及未關閉字符串字面值 (單重引號和三重引號) 的錯誤現(xiàn)在會指向字符串的開頭而不是報告 EOF/EOL。

這些改進的靈感來自 PyPy 解釋器之前所進行的工作。

(由 Pablo Galindo 在 bpo-42864 以及 Batuhan Taskaya 在 bpo-40176 中貢獻。)

解釋器所引發(fā)的 SyntaxError 異?,F(xiàn)在將高亮構成語法錯誤本身的完整異常錯誤內(nèi)容,而不是僅提示檢測到問題的位置。 這樣,不再(同 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

現(xiàn)在 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 中貢獻。)

  • 在多項集字面值中和表達式之間缺失逗號:

    >>>
    >>> 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 中貢獻)

  • try 代碼塊不帶 exceptfinally 代碼塊:

    >>>
    >>> 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 中貢獻。)

IndentationError?

許多 IndentationError 異?,F(xiàn)在具有更多上下文來提示是何種代碼塊需要縮進,包括語句的位置:

>>>
>>> def foo():
...    if lel:
...    x = 2
  File "<stdin>", line 3
    x = 2
    ^
IndentationError: expected an indented block after 'if' statement in line 2

AttributeError?

當打印 AttributeError 時,PyErr_Display() 將提供引發(fā)異常的對象中類似屬性名稱的建議:

>>>
>>> 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 中貢獻。)

警告

請注意如果未調(diào)用 PyErr_Display() 來顯示錯誤則此特性將沒有效果,這可能發(fā)生在使用了某些其他自定義錯誤顯示函數(shù)的時候。 這在某些 REPL 例如 IPython 上是一種常見的情況。

NameError?

當打印解釋器所引發(fā)的 NameError 時,PyErr_Display() 將提供引發(fā)異常的函數(shù)中類似變量名稱的建議:

>>>
>>> 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 中貢獻。)

警告

請注意如果未調(diào)用 PyErr_Display() 來顯示錯誤則此特性將沒有效果,這可能發(fā)生在使用了某些其他自定義錯誤顯示函數(shù)的時候。 這在某些 REPL 例如 IPython 中是一種常見的情況。

PEP 626:在調(diào)試和其他工具中使用精確的行號?

PEP 626 帶來了更精確可靠的行號用于調(diào)試、性能分析和測試工具。 所有被執(zhí)行的代碼行都會并且只有被執(zhí)行的代碼行才會生成帶有正確行號的追蹤事件。

幀對象的 f_lineno 屬性將總是包含預期的行號。

代碼對象的 co_lnotab 屬性已被棄用并將在 3.12 中被移除。 需要從偏移量轉換為行號的代碼應改用新的 co_lines() 方法。

PEP 634:結構化模式匹配?

增加了采用模式加上相應動作的 match 語句case 語句 的形式的結構化模式匹配。 模式由序列、映射、基本數(shù)據(jù)類型以及類實例構成。 模式匹配使得程序能夠從復雜的數(shù)據(jù)類型中提取信息、根據(jù)數(shù)據(jù)結構實現(xiàn)分支,并基于不同的數(shù)據(jù)形式應用特定的動作。

語法與操作?

模式匹配的通用語法如下:

match subject:
    case <pattern_1>:
        <action_1>
    case <pattern_2>:
        <action_2>
    case <pattern_3>:
        <action_3>
    case _:
        <action_wildcard>

match 語句接受一個表達式并將其值與以一個或多個 case 語句塊形式給出的一系列模式進行比較。 具體來說,模式匹配的操作如下:

  1. 使用具有特定類型和形狀的數(shù)據(jù) (subject)

  2. 針對 subjectmatch 語句中求值

  3. 從上到下對 subject 與 case 語句中的每個模式進行比較直到確認匹配到一個模式。

  4. 執(zhí)行與被確認匹配的模式相關聯(lián)的動作。

  5. 如果沒有確認到一個完全的匹配,則如果提供了使用通配符 _ 的最后一個 case 語句,則它將被用作已匹配模式。 如果沒有確認到一個完全的匹配并且不存在使用通配符的 case 語句,則整個 match 代碼塊不執(zhí)行任何操作。

聲明性方式?

讀者可能是通過 C, Java 或 JavaScript (以及其他許多語言) 中的 switch 語句將一個目標 (數(shù)據(jù)對象) 與一個字面值 (模式) 進行匹配的簡單例子了解到模式匹配的概念的。 switch 語句常常被用來將一個對象/表達式與包含在 case 語句中的字面值進行比較。

更強大的模式匹配例子可以在 Scala 和 Elixir 等語言中找到。 這種結構化模式匹配方式是“聲明性”的并且會顯式地為所要匹配的數(shù)據(jù)指定條件(模式)。

雖然使用嵌套的“if”語句的“命令性”系列指令可以被用來完成類似結構化模式匹配的效果,但它沒有“聲明性”方式那樣清晰。 相反地,“聲明性”方式指定了一個匹配所要滿足的條件,并且通過其顯式的模式使之更為易讀。 雖然結構化模式匹配可以采取將一個變量與一個 case 語句中的字面值進行比較的最簡單形式來使用,但它對于 Python 的真正價值在于其針對目標類型和形狀的處理操作。

簡單模式:匹配一個字面值?

讓我們把這個例子看作是模式匹配的最簡單形式:一個值,即主詞,被匹配到幾個字面值,即模式。在下面的例子中,status 是匹配語句的主詞。模式是每個 case 語句,字面值代表請求狀態(tài)代碼。匹配后,將執(zhí)行與該 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"

如果傳給上述函數(shù)的 status 為 418,則會返回 "I'm a teapot"。 如果傳給上述函數(shù)的 status 為 500,則帶有 _ 的 case 語句將作為通配符匹配,并會返回 "Something's wrong with the internet"。 請注意最后一個代碼塊:變量名 _ 將作為 通配符 并確保目標將總是被匹配。 _ 的使用是可選的。

你可以使用 | (“ or ”)在一個模式中組合幾個字面值:

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 語句中使用 _,可能會出現(xiàn)不存在匹配的情況。如果不存在匹配,則行為是一個 no-op。例如,如果傳入了值為 500 的 status ,就會發(fā)生 no-op。

帶有字面值和變量的模式?

模式可以看起來像解包形式,而且模式可以用來綁定變量。在這個例子中,一個數(shù)據(jù)點可以被解包為它的 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 。

模式和類?

如果你使用類來結構化你的數(shù)據(jù),你可以使用類的名字,后面跟一個類似構造函數(shù)的參數(shù)列表,作為一種模式。這種模式可以將類的屬性捕捉到變量中:

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")
帶有位置參數(shù)的模式?

你可以在某些為其屬性提供了排序的內(nèi)置類(例如 dataclass)中使用位置參數(shù)。 你也可以通過在你的類中設置 __match_args__ 特殊屬性來為模式中的屬性定義一個專門的位置。 如果它被設為 ("x", "y"),則以下模式均為等價的(并且都是將 y 屬性綁定到 var 變量):

Point(1, var)
Point(1, y=var)
Point(x=1, y=var)
Point(y=var, x=1)

嵌套模式?

模式可以任意地嵌套。 例如,如果我們的數(shù)據(jù)是由點組成的短列表,則它可以這樣被匹配:

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 將繼續(xù)嘗試下一個 case 語句塊。 請注意值的捕獲發(fā)生在約束項被求值之前。:

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, *_) 可以匹配包含兩個條目的序列而不必綁定其余的條目。

  • 映射模式: {"bandwidth": b, "latency": l} 會從一個字典中捕獲 "bandwidth""latency" 值。 與序列模式不同,額外的鍵會被忽略。 也支持通配符 **rest。 (但 **_ 是冗余的,因而不被允許。)

  • 子模式可使用 as 關鍵字來捕獲:

    case (Point(x1, y1), Point(x2, y2) as p2): ...
    

    x1, y1, x2, y2 等綁定就如你在沒有 as 子句的情況下所期望的,而 p2 會綁定目標的整個第二項。

  • 大多數(shù)字面值是按相等性比較的。 但是,單例對象 True, FalseNone 則是按標識號比較的。

  • 命名常量也可以在模式中使用。 這些命名常量必須為帶點號的名稱以防止常量被解讀為捕獲變量:

    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 :(")
    

完整規(guī)格說明參見 PEP 634。 動機與理由參見 PEP 635,更詳細的教程參見 PEP 636。

可選的 EncodingWarningencoding="locale" 選項?

TextIOWrapperopen() 的默認編碼格式取決于具體的平臺和語言區(qū)域設置。 由于 UTF-8 被用于大多數(shù) Unix 平臺,當打開 UTF-8 文件 (例如 JSON, YAML, TOML, Markdown) 時省略 encoding 選項是一個非常常見的錯誤。 例如:

# 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 為真值并使用了語言區(qū)域指定的默認編碼格式時被發(fā)出。

增加了 -X warn_default_encoding 選項和 PYTHONWARNDEFAULTENCODING 來啟用相應警告。

請參閱 文本編碼格式 了解更多信息。

其他語言特性修改?

  • int 類型新增了一個方法 int.bit_count(),返回給定整數(shù)的二進制展開中值為一的位數(shù),或稱“比特計量”。 (由 Niklas Fiekas 在 bpo-29882 中貢獻。)

  • 現(xiàn)在 dict.keys(), dict.values()dict.items() 所返回的視圖都有一個 mapping 屬性,它給出包裝了原始字典的 types.MappingProxyType 對象。 (由 Dennis Sweeney 在 bpo-40890 中貢獻。)

  • PEP 618: 現(xiàn)在 zip() 函數(shù)有一個可選的 strict 旗標,用于要求所有可迭代對象的長度都相等。

  • 接受整數(shù)參數(shù)的內(nèi)置和擴展函數(shù)不再接受 Decimal, Fraction 以及其他可被轉換為整數(shù)但會丟失精度(即具有 __int__() 方法但沒有 __index__() 方法)的對象。 (由 Serhiy Storchaka 在 bpo-37999 中貢獻。)

  • 如果 object.__ipow__() 返回 NotImplemented,該運算符將正確地按照預期回退至 object.__pow__()object.__rpow__()。 (由 Alex Shkop 在 bpo-38302 中貢獻。)

  • 現(xiàn)在賦值表達式可以不帶圓括號地在集合字面值和集合推導式中使用,也可以在序列索引號中使用(但不能用于切片)。

  • 函數(shù)具有一個新的 __builtins__ 屬性,當函數(shù)被執(zhí)行時它會被用于查找內(nèi)置符號,而不是在 __globals__['__builtins__'] 中查找。 如果 __globals__["__builtins__"] 存在則該屬性將基于它來初始化,否則將基于當前的內(nèi)置函數(shù)。 (由 Mark Shannon 在 bpo-42990 中貢獻。)

  • 增加了兩個新的內(nèi)置函數(shù) —— aiter()anext() 以分別提供與 iter()next() 對應的異步版本。 (由 Joshua Bronson, Daniel Pope 和 Justin Wang 在 bpo-31861 中貢獻。)

  • 靜態(tài)方法 (@staticmethod) 和類方法 (@classmethod) 現(xiàn)在會繼承方法屬性 (__module__, __name__, __qualname__, __doc__, __annotations__) 并具有一個新的 __wrapped__ 屬性。 此外,靜態(tài)方法現(xiàn)在還是與常規(guī)函數(shù)一樣的可調(diào)用對象。 (由 Victor Stinner 在 bpo-43682 中貢獻。)

  • 復雜目標的注解( PEP 526 定義的除 simple name 之外的一切復雜目標)在運行時不再受 from __future__ import annotations 的影響。(由Batuhan Taskaya 在 bpo-42737 中貢獻)。

  • 類和模塊對象現(xiàn)在可以按需創(chuàng)建空的注解字典。為保證向下兼容,這些注解數(shù)據(jù)將存儲于對象的 __dict__ 中。這改進了 __annotations__ 的最佳用法;更多信息請參閱 對象注解屬性的最佳實踐 。(由 Larry Hastings 在 bpo-43901 中貢獻)

  • 由于會產(chǎn)生副作用,現(xiàn)在 from __future__ import annotations 時禁止使用包含 yield 、 yield fromawait 或已命名表達式的注解。(由 Batuhan Taskaya 在 bpo-42725 中貢獻)

  • 未綁定變量、super() 和其他可能改變符號表處理的表達式,現(xiàn)在在 from __future__ import annotations 時不能用作注解。(由 Batuhan Taskaya 在 bpo-42725 中貢獻)

  • float 類型和 decimal.Decimal 類型的 NaN 值的哈希值現(xiàn)在取決于對象身份。以前,即便 NaN 值彼此不等,也都是哈希為 0。在創(chuàng)建包含多個 NaN 的字典和集合時,由于哈希沖突過度,導致了運行代價可能會二次方增長。(由 Raymond Hettinger 在 bpo-43475 中貢獻)

  • A SyntaxError (instead of a NameError) will be raised when deleting the __debug__ constant. (Contributed by Dong-hee Na in bpo-45000.)

  • SyntaxError exceptions now have end_lineno and end_offset attributes. They will be None if not determined. (Contributed by Pablo Galindo in bpo-43914.)

新增模塊?

  • 無。

改進的模塊?

asyncio?

加入了缺失的 connect_accepted_socket() 方法。(由 Alex Gr?nholm 在 bpo-41332 中貢獻)

argparse?

在 argparse 的幫助中,將“可選參數(shù)”這一誤導性短語改為“可選項”。某些測試代碼如果依賴精確的輸出匹配,可能需要調(diào)整。(由 Raymond Hettinger 在 bpo-9694 中貢獻)

array?

現(xiàn)在, array.arrayindex() 方法擁有可選的 startstop 參數(shù)。(由 Anders Lorentsen 和 Zackery Spytz 在 bpo-31956 中貢獻)

asynchat、asyncore 和 smtpd?

從 Python 3.6 開始,這些模塊在其文檔中已被標為廢棄?,F(xiàn)在這三個模塊都增加了一個導入時警告 DeprecationWarning

base64?

增加 base64.b32hexencode()base64.b32hexdecode() 以支持帶有擴展十六進制字母的 Base32 編碼。

bdb?

增加 clearBreakpoints() ,用于重置所有已設斷點。(由 Irit Katriel 在 bpo-24160 中貢獻)

bisect?

Added the possibility of providing a key function to the APIs in the bisect module. (Contributed by Raymond Hettinger in bpo-4356.)

編碼器?

增加一個 codecs.unregister() 函數(shù),用于取消對編解碼器搜索函數(shù)的注冊。(由 Hai Shi 在 bpo-41842 中貢獻)

collections.abc?

現(xiàn)在, parameterized genericcollections.abc.Callable__args__typing.Callable 一致了。 collections.abc.Callable generic 現(xiàn)在將類型參數(shù)扁平化了,類似于 typing.Callable 當前的做法。這意味著 collections.abc.Callable[[int, str], str] 將帶有 (int, str, str) 的參數(shù) __args__;以前是 ([int, str], str) 。為了做到這一變化, types.GenericAlias 現(xiàn)在可以被子類化,當對 collections.abc.Callable 類型進行下標訪問時,將返回一個子類。注意,collections.abc.Callable 非法的參數(shù)化形式可能會觸發(fā) 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 中增加的擴展顏色函數(shù)將會由 curses.color_content() 、 curses.init_color() 、 curses.init_pair()curses.pair_content() 透明地使用。新增的函數(shù) curses.has_extended_color_support() 將指明下層的 ncurses 庫是否提供了擴展顏色支持。(由 Jeffrey Kintscher 和 Hans Petter Jansson 在 bpo-36982 中貢獻)

現(xiàn)在常量 BUTTON5_* 如果是由底層的 curses 庫提供的,則會在 curses 模塊中體現(xiàn)。(由 Zackery Spytz 在 bpo-39273 中貢獻)

dataclasses?

__slots__?

Added slots parameter in dataclasses.dataclass() decorator. (Contributed by Yurii Karabas in bpo-42269)

Keyword-only fields?

dataclasses now supports fields that are keyword-only in the generated __init__ method. There are a number of ways of specifying keyword-only fields.

You can say that every field is keyword-only:

from dataclasses import dataclass

@dataclass(kw_only=True)
class Birthday:
    name: str
    birthday: datetime.date

Both name and birthday are keyword-only parameters to the generated __init__ method.

You can specify keyword-only on a per-field basis:

from dataclasses import dataclass, field

@dataclass
class Birthday:
    name: str
    birthday: datetime.date = field(kw_only=True)

Here only birthday is keyword-only. If you set kw_only on individual fields, be aware that there are rules about re-ordering fields due to keyword-only fields needing to follow non-keyword-only fields. See the full dataclasses documentation for details.

You can also specify that all fields following a KW_ONLY marker are keyword-only. This will probably be the most common usage:

from dataclasses import dataclass, KW_ONLY

@dataclass
class Point:
    x: float
    y: float
    _: KW_ONLY
    z: float = 0.0
    t: float = 0.0

Here, z and t are keyword-only parameters, while x and y are not. (Contributed by Eric V. Smith in bpo-43532)

distutils?

整個 distutils 包已被廢棄,將在 Python 3.12 中移除。其用指定包構建程序的功能已被第三方軟件包 setuptoolspackaging 完全取代,而且大多數(shù)其他常用的 API 在標準庫的其他地方都可以調(diào)用(如 platform 、 shutil 、 subprocesssysconfig)。目前沒有遷移 distutils 其他功能的計劃,用到其他功能的應用程序應該準備好自己保留一份拷貝。請參考 PEP 632 。

在 Python 3.8 中廢棄的 bdist_wininst 命令已被移除?,F(xiàn)在在 Windows 中發(fā)布二進制包推薦采用 bdist_wheel 命令。(由 Victor Stinner 在 bpo-42802 中貢獻)

doctest?

若模塊中沒有定義 __loader__ ,則回退至使用 __spec__.loader 。(由 Brett Cannon 在 bpo-42133 中貢獻)

encodings?

現(xiàn)在 encodings.normalize_encoding() 會忽略非 ASCII 字符。(由 Hai Shi 在 bpo-39337 中貢獻)

enum?

Enum __repr__() now returns enum_name.member_name and __str__() now returns member_name. Stdlib enums available as module constants have a repr() of module_name.member_name. (Contributed by Ethan Furman in bpo-40066.)

Add enum.StrEnum for enums where all members are strings. (Contributed by Ethan Furman in bpo-41816.)

fileinput?

fileinput.input()fileinput.FileInput 中增加了 encodingerrors 形參。 (由 Inada Naoki 在 bpo-43712 中貢獻。)

現(xiàn)在 fileinput.hook_compressed() 會在 mode 為 "r" 且文件被壓縮時返回 TextIOWrapper,與未壓縮文件一致。 (由 Inada Naoki 在 bpo-5758 中貢獻。)

faulthandler?

現(xiàn)在 faulthandler 模塊會檢測在垃圾回收期間是否發(fā)生嚴重錯誤。 (由 Victor Stinner 在 bpo-44466 中貢獻)

gc?

gc.get_objects(), gc.get_referrers()gc.get_referents() 添加了審計鉤子。 (由 Pablo Galindo 在 bpo-43439 中貢獻。)

glob?

glob()iglob() 中增加了 root_dirdir_fd 形參,用于指定搜索的根目錄。(由 Serhiy Storchaka 在 bpo-38144 中貢獻)

hashlib?

hashlib 模塊要求 OpenSSL 1.1.1 或更新版本。 (由 Christian Heimes 在 PEP 644bpo-43669 中貢獻。)

hashlib 模塊已初步支持 OpenSSL 3.0.0。 (由 Christian Heimes 在 bpo-38820 及其他問題事項中貢獻。)

純 Python 的回退版 pbkdf2_hmac() 已被棄用。 未來 PBKDF2-HMAC 將僅在 Python 帶有 OpenSSL 編譯時才可用。(由 Christian Heimes 在 bpo-43880 中貢獻)

hmac?

現(xiàn)在 hmac 模塊會在內(nèi)部使用 OpenSSL 的 HMAC 實現(xiàn)。 (由 Christian Heimes 在 bpo-40645 中貢獻。)

IDLE 與 idlelib?

Make IDLE invoke sys.excepthook() (when started without '-n'). User hooks were previously ignored. (Contributed by Ken Hilton in bpo-43008.)

Rearrange the settings dialog. Split the General tab into Windows and Shell/Ed tabs. Move help sources, which extend the Help menu, to the Extensions tab. Make space for new options and shorten the dialog. The latter makes the dialog better fit small screens. (Contributed by Terry Jan Reedy in bpo-40468.) Move the indent space setting from the Font tab to the new Windows tab. (Contributed by Mark Roseman and Terry Jan Reedy in bpo-33962.)

The changes above were backported to a 3.9 maintenance release.

增加了 Shell 側欄。 將主提示符(“>>>”)移至側欄。二級提示符(“...”)也加入側欄。在編輯器的行號側欄上鼠標單擊和可選的拖動,會選定一行或多行文本。在選定文本行后右擊將顯示包含“copy with prompts”的上下文菜單。這會將側欄的提示符與選定文本行合并。該選項也會在文本的上下文菜單中顯示。(由 Tal Einat 在 bpo-37903 中貢獻)

Use spaces instead of tabs to indent interactive code. This makes interactive code entries 'look right'. Making this feasible was a major motivation for adding the shell sidebar. (Contributed by Terry Jan Reedy in bpo-37892.)

Highlight the new soft keywords match, case, and _ in pattern-matching statements. However, this highlighting is not perfect and will be incorrect in some rare cases, including some _-s in case patterns. (Contributed by Tal Einat in bpo-44010.)

New in 3.10 maintenance releases.

Apply syntax highlighting to .pyi files. (Contributed by Alex Waygood and Terry Jan Reedy in bpo-45447.)

importlib.metadata?

importlib_metadata 4.6(history)的功能一致。

importlib.metadata entry points now provide a nicer experience for selecting entry points by group and name through a new importlib.metadata.EntryPoints class. See the Compatibility Note in the docs for more info on the deprecation and usage.

添加了 importlib.metadata.packages_distributions(),用于將頂級 Python 模塊和包解析為其 importlib.metadata.Distributions。

inspect?

若模塊中沒有定義 __loader__ ,則回退至使用 __spec__.loader 。(由 Brett Cannon 在 bpo-42133 中貢獻)

加入了 inspect.get_annotations(),以便安全地對對象中定義的注解進行求值。inspect.get_annotations() 也可以正確地解析字符串化的注解。 inspect.get_annotations() 現(xiàn)在應是訪問任何 Python 對象注解字典的最佳實踐;關于注解最佳用法的更多信息,請參見 對象注解屬性的最佳實踐。與之關聯(lián)的, inspect.signature() 、 inspect.Signature.from_callable()inspect.Signature.from_function() 現(xiàn)在也調(diào)用 inspect.get_annotations() 來獲取注解信息。這意味著 inspect.signature()inspect.Signature.from_callable() 現(xiàn)在也可以解析字符串化的注解了。(由 Larry Hastings 在 bpo-43817 中貢獻)

itertools?

Add itertools.pairwise(). (Contributed by Raymond Hettinger in bpo-38200.)

linecache?

若模塊中沒有定義 __loader__ ,則回退至使用 __spec__.loader 。(由 Brett Cannon 在 bpo-42133 中貢獻)

os?

為 VxWorks 實時操作系統(tǒng)加入 os.cpu_count() 的支持。(由 Peixing Xin 在:issue:41440 中貢獻)

加入一個新函數(shù) os.eventfd() 及其助手函數(shù),以封裝 Linux 的系統(tǒng)調(diào)用 eventfd2 。(由 Christian Heimes 在 bpo-41001 中貢獻)

加入 os.splice(),以便在兩個文件描述符之間移動數(shù)據(jù),而無需在內(nèi)核地址空間和用戶地址空間之間進行復制,其中一個文件描述符必須指向某個管道。(由 Pablo Galindo 在 bpo-41625 中貢獻)

為 macOS 加入 O_EVTONLY 、O_FSYNC 、 O_SYMLINKO_NOFOLLOW_ANY 。(由 Dong-hee Na 在 bpo-43106 中貢獻)

os.path?

現(xiàn)在 os.path.realpath() 可接受一個關鍵字參數(shù) strict。 若設為 True ,則在路徑不存在或遭遇循環(huán)符號鏈接時,會觸發(fā) OSError。 (由 Barney Gale 在 bpo-43757 中貢獻。)

pathlib?

PurePath.parents 加入切片支持。(由Joshua Cannon 貢獻于 bpo-35498

PurePath.parents 加入負數(shù)索引支持。(由 Yaroslav Pankovych 貢獻于 bpo-21041

加入 Path.hardlink_to 方法,取代 link_to()。該新方法的參數(shù)順序與 symlink_to() 相同。(由 Barney Gale 貢獻于 bpo-39950 中)

現(xiàn)在 pathlib.Path.stat()chmod() 接受一個關鍵字參數(shù) follow_symlinks ,以便與 os 模塊中的對應函數(shù)保持一致。(由 Barney Gale 貢獻于 bpo-39906

平臺?

加入 platform.freedesktop_os_release(),從標準文件 freedesktop.org os-release 中獲取操作系統(tǒng)標識。(由 Christian Heimes 貢獻于 bpo-28468

pprint?

現(xiàn)在 pprint.pprint() 接受一個新的關鍵字參數(shù) underscore_numbers。(由 sblondon 貢獻于 bpo-42914

現(xiàn)在 pprint 可以完美打印 dataclasses.dataclass 實例。(由 Lewis Gaul 貢獻于 bpo-43080

py_compile?

py_compile' 的命令行界面加入 `--quiet`` 選項。(由 Gregory Schevchenko 貢獻于 bpo-38731

pyclbr?

pyclbr.readline()pyclbr.readline_ex() 返回的結果樹中的``Function`` 和 Class 對象上增加一個 end_lineno 屬性。與現(xiàn)有的(開始)``lineno`` 相匹配。(由 Aviral Srivastava 貢獻于 bpo-38307

shelve?

現(xiàn)在 shelve 模塊在創(chuàng)建打包時,默認采用 pickle.DEFAULT_PROTOCOL,而不是 pickle 協(xié)議 3 。(由 Zackery Spytz 貢獻于 bpo-34204

statistics?

加入 covariance() 、Pearson 的 correlation() 和簡單的 linear_regression() 函數(shù)。(由 Tymoteusz Wo?od?ko 貢獻于 bpo-38490

site?

若模塊中沒有定義 __loader__ ,則回退至使用 __spec__.loader 。(由 Brett Cannon 在 bpo-42133 中貢獻)

socket?

現(xiàn)在異常 socket.timeoutTimeoutError 的別名。(由 Christian Heimes 在 bpo-42413 中貢獻。)

加入用 IPPROTO_MPTCP 創(chuàng)建 MPTCP 套接字的選項(由 Rui Cunha 貢獻于 bpo-43571

加入 IP_RECVTOS 選項,以便接收服務類型(ToS)或 DSCP/ECN 字段(由 Georg Sauthoff 貢獻于 bpo-44077

ssl?

ssl 模塊要求 OpenSSL 1.1.1 或更新版本。 (由 Christian Heimes 在 PEP 644bpo-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-43789bpo-43811 中貢獻。)

現(xiàn)在,已棄用函數(shù)和使用已棄用常量會導致 DeprecationWarning。 ssl.SSLContext.options 默認設置了 OP_NO_SSLv2OP_NO_SSLv3 ,因而設置此標記無法再次發(fā)出警告了。 棄用部分 列出了已棄用的特性。 (由 Christian Heimes 貢獻于 bpo-43880

現(xiàn)在,ssl 模塊默認設置的安全性提高了。默認情況下,不具備前向安全性或 SHA-1 MAC 的加密算法會被禁用。二級安全禁止安全性低于 112 位的弱 RSA、DH 和 ECC 密鑰。 SSLContext 默認的最低版本協(xié)議為 TLS 1.2。這些設置是基于 Hynek Schlawack 的研究。(由 Christian Heimes 貢獻于 bpo-43998

已棄用的協(xié)議 SSL 3.0, TLS 1.0 和 TLS 1.1 不再受到官方支持。Python 不會直接禁用。但 OpenSSL 編譯選項、發(fā)行版配置、廠商補丁和加密套件可能會阻止握手成功。

ssl.get_server_certificate() 函數(shù)加入 timeout 形參。(由 Zackery Spytz 貢獻于 bpo-31870

ssl 模塊用到了堆類型和多階段初始化。(由 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 可執(zhí)行文件的初始命令行參數(shù)列表。(由 Victor Stinner 貢獻于 bpo-23427

添加了 sys.stdlib_module_names,包含標準庫模塊名稱的列表。 (由 Victor Stinner 在 bpo-42955 中貢獻。)

_thread?

現(xiàn)在, _thread.interrupt_main() 接受一個可選的信號值參數(shù)進行模擬(默認仍為 signal.SIGINT)。(由 Antoine Pitrou 貢獻于 bpo-43356

threading?

加入 threading.gettrace()threading.getprofile() ,分別用于獲取 threading.settrace()threading.setprofile() 設置的函數(shù)。(由Mario Corchero 貢獻于 bpo-42251

加入 threading.__excepthook__ ,用于獲取 threading.excepthook() 的初始值,以防被設為一個差勁或其他的值。(由 Mario Corchero 貢獻于 bpo-42308

traceback?

現(xiàn)在,format_exception() 、 format_exception_only()print_exception() 函數(shù)可以接受一個異常對象,作為唯一的位置參數(shù)。(由 Zackery Spytz 和 Matthias Bussonnier 貢獻于 bpo-26389

types?

重新引入 types.EllipsisTypetypes.NoneTypetypes.NotImplementedType 類,以提供一套新的類型,可供類型檢查程序解釋。(由 Bas van Beek 貢獻于 bpo-41810

typing?

For major changes, see 有關類型提示的新增特性.

typing.Literal 的行為被改為遵循 PEP 586 并匹配該 PEP 所描述的靜態(tài)類型檢查器的行為。

  1. Literal 現(xiàn)在將是去重后的形參。

  2. Literal 對象的相等性比較現(xiàn)在將與順序無關。

  3. Literal comparisons now respect types. For example, Literal[0] == Literal[False] previously evaluated to True. It is now False. To support this change, the internally used type cache now supports differentiating types.

  4. 現(xiàn)在,如果 Literal 對象的任何參數(shù)都不是 hashable ,在相等性比較時將引發(fā) TypeError 異常。請注意,在聲明 Literal 時,參數(shù)不可哈希不會拋出錯誤:

    >>>
    >>> 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 中貢獻。)

加入新函數(shù) typing.is_typeddict(),以內(nèi)部檢查注解是否為 typing.TypedDict。(由 Patrick Reader 貢獻于 bpo-41792

現(xiàn)在,如果 typing.Protocol 的子類只聲明了數(shù)據(jù)變量,那么在用 isinstance 檢查時會引發(fā) TypeError,除非是用 runtime_checkable() 裝飾的。以前,這是靜默通過檢查的。如果用戶需要運行時協(xié)議,應該用 runtime_checkable() 裝飾器來裝飾其子類。(由 Yurii Karabas 貢獻于 bpo-38908

Importing from the typing.io and typing.re submodules will now emit DeprecationWarning. These submodules have been deprecated since Python 3.8 and will be removed in a future version of Python. Anything belonging to those submodules should be imported directly from typing instead. (Contributed by Sebastian Rittau in bpo-38291)

unittest?

加入新方法 assertNoLogs() ,以補充現(xiàn)有的 assertLogs()。(由 Kit Yan Choi 貢獻于 bpo-39385

urllib.parse?

Python 3.10 以下版本允許在 urllib.parse.parse_qs()urllib.parse.parse_qsl() 中同時使用 ;& 作為查詢參數(shù)分隔符。出于安全考慮,并符合 W3C 最新的建議,這已經(jīng)被修改為只允許用一種分隔符,默認值為 &。 這一改變也影響到了 cgi.parse()cgi.parse_multipart(),因為他們內(nèi)部用到了這些函數(shù)。更多細節(jié),請參閱各自的文檔。(由 Adam Goldschmidt 、 Senthil Kumaran 和 Ken Jin 貢獻于 bpo-42967

xml?

xml.sax.handler 模塊中加入一個 LexicalHandler 類。(由 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

性能優(yōu)化?

  • 現(xiàn)在,構造函數(shù) str()bytes()bytearray() 速度更快了(小對象大約提速 30-40%)。(由 Serhiy Storchaka 貢獻于 bpo-41334

  • 現(xiàn)在, runpy 導入的模塊變少了。python3 -m module-name 命令的啟動時間平均加快 1.4 倍。在 Linux 上,Python 3.9 的 python3 -I -m module-name 導入了69個模塊,而 Python 3.10 只導入了 51個模塊(少了 18 個)。(由 Victor Stinner 貢獻于 bpo-41006bpo-41718

  • 現(xiàn)在, LOAD_ATTR 指令會使用新的“單獨操作碼緩存”機制。對于常規(guī)屬性大約會提速 36%,而對于槽位屬性會加快 44%。(由 Pablo Galindo 和 Yury Selivanov 貢獻于 bpo-42093 ),并由 Guido van Rossum 貢獻于 bpo-42927,基于最初在 PyPy 和 MicroPython 中實現(xiàn)的思路。)

  • 現(xiàn)在,當用 --enable-optimizations 構建 Python 時,會在編譯和鏈接命令行中添加 -fno-semantic-interposition。 這會讓用帶參數(shù) --enable-sharedgcc 構建 Python 解釋器時提速 30%。詳情請參閱`這篇文章 <https://developers.redhat.com/blog/2020/06/25/red-hat-enterprise-linux-8-2-brings-faster-python-3-8-run-speeds/>`_ 。(由 Victor Stinner 和 Pablo Galindo 貢獻于 bpo-38980

  • bz2 / lzma / zlib 模塊用了新的輸出緩沖區(qū)管理代碼,并在 _compression.DecompressReader 類中添加``.readall()`` 函數(shù)。現(xiàn)在,bz2 解壓過程提速了 1.09 倍 ~ 1.17 倍,lzma 解壓快了 1.20 倍 ~ 1.32 倍,GzipFile.read(-1) 快了 1.11 倍 ~ 1.18 倍。(由 Ma Lin 貢獻,由 Gregory P. Smith 審查, bpo-41486

  • 在使用字符串式的注解時,函數(shù)的注解字典不再是在函數(shù)創(chuàng)建時建立了。取而代之的是,注解被存儲為一個字符串元組,而函數(shù)對象在需要時再延遲轉換為注解字典。這一優(yōu)化將定義帶注解函數(shù)的CPU時間減少了一半。(由 Yurii Karabas 和 Inada Naoki 貢獻于 bpo-42202

  • 現(xiàn)在,子串搜索函數(shù),如 str1 in str2str2.find(str1) ,有時會采用Crochemore & Perrin的“二路歸并”字符串搜索算法,以避免長字符串的二次檢索行為。(由 Dennis Sweeney 貢獻于 bpo-41972

  • _PyType_Lookup() 加入了少許優(yōu)化,以提高類型屬性緩存查詢在常見命中情況下的性能。這使得解釋器的平均速度提高了 1.04 倍。(由 Dino Viehland 貢獻于 bpo-43452

  • 現(xiàn)在,以下內(nèi)置函數(shù)支持更快的 PEP 590 vectorcall 調(diào)用約定: map() 、 filter() 、 reversed() 、 bool()float() 。(由 Dong-hee Na 和 Jeroen Demeyer 貢獻于 bpo-43575 、 bpo-43287 、 bpo-41922 、 bpo-41873bpo-41870

  • 通過移除內(nèi)部的 RLock ,BZ2File 的性能得以改善。這使得 BZ2File 在面對多個同時讀寫線程時變得不再安全,類似一直如此的 gziplzma 中的對應類。(由 Inada Naoki 貢獻于 bpo-43785

棄用?

移除?

  • 移除了 complex 類的特殊方法 __int__, __float__, __floordiv__, __mod__, __divmod__, __rfloordiv__, __rmod____rdivmod__。 它們總是會引發(fā) TypeError。 (由 Serhiy Storchaka 在 bpo-41974 中貢獻。)

  • ParserBase.error() 方法(來自私有且未記入文檔的 _markupbase 模塊)已被移除。 html.parser.HTMLParserParserBase 的唯一子類并且它的 error() 實現(xiàn)在 Python 3.5 中已被移除。 (由 Berker Peksag 在 bpo-31844 中貢獻。)

  • 移除了 unicodedata.ucnhash_CAPI 屬性,它是一個內(nèi)部 PyCapsule 對象。 相關聯(lián)的私有 _PyUnicode_Name_CAPI 結構體已被移至內(nèi)部 C API。 (由 Victor Stinner 在 bpo-42157 中貢獻。)

  • 移除了 parser 模塊,它在 3.9 中由于切換到新的 PEG 解析器而與僅被舊解析器所使用的 C 源文件和頭文件一起被棄用,包括 node.h, parser.h, graminit.hgrammar.h。

  • 移除了公有 C API 函數(shù) PyParser_SimpleParseStringFlags, PyParser_SimpleParseStringFlagsFilename, PyParser_SimpleParseFileFlagsPyNode_Compile,它們在 3.9 中由于切換到新的 PEG 解析器而被棄用。

  • 移除了 formatter 模塊,它在 Python 3.4 中已被棄用。 它相當過時、極少被使用,并且未經(jīng)測試。 它最初計劃在 Python 3.6 中移除,但此移除被改為延遲到 Python 2.7 生命期結束之后。 現(xiàn)有用戶應當將他們用到的所有類都拷貝到自己的代碼中。 (由 Dong-hee Na 和 Terry J. Reedy 在 bpo-42299 中貢獻。)

  • 移除了 PyModule_GetWarningsModule() 函數(shù),現(xiàn)在它由于 _warnings 模塊在 2.6 中被轉換為內(nèi)置模塊而變得沒有用處。 (由 Hai Shi 在 bpo-42599 中貢獻。)

  • collections 模塊中移除了已被棄用的 容器抽象基類 的別名。 (由 Victor Stinner 在 bpo-37324 中貢獻。)

  • loop 形參已從大部分 asyncio高層級 API 中被移除,之前它們在 Python 3.8 中已被棄用。 這一改變的動機是多方面的:

    1. 這簡化了高層級 API。

    2. 高層級 API 中的這些函數(shù)自 Python 3.7 起已經(jīng)會隱式地獲取當前線程正在運行的事件循環(huán)。 在大多數(shù)正常使用場景中都沒有必要向 API 傳入事件循環(huán)。

    3. 在處理不同線程中運行的事件循環(huán)時傳遞事件循環(huán)特別容易產(chǎn)生錯誤。

    Note that the low-level API will still accept loop. See Python API 的變化 for examples of how to replace existing code.

    (由 Yurii Karabas, Andrew Svetlov, Yury Selivanov 和 Kyle Stanley 在 bpo-42392 中貢獻。)

移植到 Python 3.10?

本節(jié)列出了先前描述的更改以及可能需要更改代碼的其他錯誤修正.

Python 語法中的變化?

  • Deprecation warning is now emitted when compiling previously valid syntax if the numeric literal is immediately followed by a keyword (like in 0in x). In future releases it will be changed to syntax warning, and finally to a syntax error. To get rid of the warning and make the code compatible with future releases just add a space between the numeric literal and the following keyword. (Contributed by Serhiy Storchaka in bpo-43833).

Python API 的變化?

  • traceback 模塊中的 format_exception() 、 format_exception_only()print_exception() 函數(shù)的 etype 參數(shù)已更名為 exc 。(由 Zackery Spytz 和 Matthias Bussonnier 貢獻于 bpo-26389

  • atexit : 在 Python 退出時,若用 atexit.register() 注冊的回調(diào)失敗,現(xiàn)在會記錄其異常。以前,只有部分異常被記錄,最后一個異??偸潜混o默忽略。(由 Victor Stinner 貢獻于 bpo-42639

  • 現(xiàn)在,泛型 collections.abc.Callable 的類型參數(shù)扁平化了,類似于 typing.Callable 目前的做法。這意味著 collections.abc.Callable[[int, str], str]__args__ 將為 (int, str, str);而以前是 ([int, str], str)。 通過 typing.get_args()__args__ 訪問參數(shù)的代碼需要考慮到這一變化。此外,為 collections.abc.Callable 給出無效參數(shù)可能會引發(fā) TypeError ,而在 Python 3.9 中則可能會靜默傳入。(由 Ken Jin 貢獻于 bpo-42195

  • 現(xiàn)在,如果給定的形參不是 16 位無符號整數(shù), socket.htons()socket.ntohs() 會引發(fā) OverflowError 而非 DeprecationWarning。 (由 Erlend E. Aasland 在 bpo-42393 中貢獻。)

  • The loop parameter has been removed from most of asyncio's high-level API following deprecation in Python 3.8.

    現(xiàn)在如下協(xié)程:

    async def foo(loop):
        await asyncio.sleep(1, loop=loop)
    

    應替換為:

    async def foo():
        await asyncio.sleep(1)
    

    如果 foo() 被特別設計成 運行于當前線程的運行事件循環(huán)中(比如運行在另一個線程的事件循環(huán)中),請考慮使用 asyncio.run_coroutine_threadsafe() 來代替。

    (由 Yurii Karabas, Andrew Svetlov, Yury Selivanov 和 Kyle Stanley 在 bpo-42392 中貢獻。)

  • The types.FunctionType constructor now inherits the current builtins if the globals dictionary has no "__builtins__" key, rather than using {"None": None} as builtins: same behavior as eval() and exec() functions. Defining a function with def function(...): ... in Python is not affected, globals cannot be overridden with this syntax: it also inherits the current builtins. (Contributed by Victor Stinner in bpo-42990.)

C API 的變化?

  • 由于換成了新的 PEG 解析程序,C 語言 API 函數(shù)``PyParser_SimpleParseStringFlags``、PyParser_SimpleParseStringFlagsFilename、PyParser_SimpleParseFileFlagsPyNode_Compile``以及這些函數(shù)用到的類型 ``struct _node 已被刪除。

    現(xiàn)在應該用 Py_CompileString() 將源代碼直接編譯為代碼對象。然后可以用 PyEval_EvalCode() 之類的東西來對其求值。

    特別地:

    • PyParser_SimpleParseStringFlagsPyNode_Compile 的調(diào)用,可以由 Py_CompileString() 代替。

    • PyParser_SimpleParseFileFlags 沒有直接替代品。要從 FILE * 參數(shù)編譯代碼,需要先用 C 語言讀取文件,然后將結果緩沖區(qū)傳給 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);
      
    • For FrameObject objects, the f_lasti member now represents a wordcode offset instead of a simple offset into the bytecode string. This means that this number needs to be multiplied by 2 to be used with APIs that expect a byte offset instead (like PyCode_Addr2Line() for example). Notice as well that the f_lasti member of FrameObject objects is not considered stable: please use PyFrame_GetLineNumber() instead.

CPython 字節(jié)碼的改變?

  • MAKE_FUNCTION 指令現(xiàn)在可以接受一個字典或一個字符串元組作為函數(shù)的標注。 (由 Yurii Karabas 和 Inada Naoki 在 bpo-42202 中貢獻。)

編譯版的變化?

  • PEP 644 :Python 現(xiàn)在要求 OpenSSL 1.1.1 以上版本。不再支持 OpenSSL 1.0.2。(由 Christian Heimes 貢獻于 bpo-43669

  • 編譯 Python 現(xiàn)在需要用到 C99 函數(shù) snprintf()vsnprintf() 。(由 Victor Stinner 貢獻于 bpo-36020

  • sqlite3 requires SQLite 3.7.15 or higher. (Contributed by Sergey Fedoseev and Erlend E. Aasland in bpo-40744 and bpo-40810.)

  • 現(xiàn)在, atexit 模塊必須編譯為內(nèi)置模塊。(由 Victor Stinner 貢獻于 bpo-42639

  • configure 腳本中加入 --disable-test-modules 選項:不編譯也不安裝 test 模塊。(由 Xavier de Gaye、Thomas Petazzoni 和 Peixing Xin 貢獻于 bpo-27640

  • ./configure 腳本中加入 --with-wheel-pkg-dir=PATH 選項。如果指定了該選項, ensurepip 模塊會在該目錄下查找 setuptoolspip 包:如果兩者都存在,就會使用這些包,而不是surepip 綁定的包。

    某些 Linux 發(fā)行版的打包策略建議不要綁定依賴關系。比如 Fedora 在``/usr/share/python-wheels/`` 目錄下安裝 wheel 包,而不安裝``ensurepip._bundled`` 包。

    (由 Victor Stinner 貢獻于 bpo-42856

  • 增加了新的 configure --without-static-libpython 選項 ,用于標明不編譯 libpythonMAJOR.MINOR.a 靜態(tài)庫并且不安裝 python.o 對象文件。

    (由 Victor Stinner 在 bpo-43103 中貢獻。)

  • The configure script now uses the pkg-config utility, if available, to detect the location of Tcl/Tk headers and libraries. As before, those locations can be explicitly specified with the --with-tcltk-includes and --with-tcltk-libs configuration options. (Contributed by Manolis Stamatogiannakis in bpo-42603.)

  • configure 腳本加入 --with-openssl-rpath 選項。該選項簡化了用定制版本 OpenSSL 編譯 Python 的過程,例如 ./configure --with-openssl=/path/to/openssl --with-openssl-rpath=auto。(由 Christian Heimes 貢獻于 bpo-43466

C API 的變化?

PEP 652:穩(wěn)定版 ABI 的維護?

現(xiàn)在,用于擴展模塊或嵌入 Python 的穩(wěn)定版 ABI (應用程序二進制接口)已有顯式的定義。 C API Stability 描述了 C API 和 ABI 穩(wěn)定性保證和穩(wěn)定版 ABI 的最佳實踐。

(由 Petr Viktorin 在 PEP 652bpo-43795 中貢獻。).)

新的特性?

  • 現(xiàn)在 PyNumber_Index() 的結果一定是 int 類型。此前可能是 int 的子類實例。(由 Serhiy Storchaka 貢獻于 bpo-40792

  • Add a new orig_argv member to the PyConfig structure: the list of the original command line arguments passed to the Python executable. (Contributed by Victor Stinner in bpo-23427.)

  • 加入宏 PyDateTime_DATE_GET_TZINFO()PyDateTime_TIME_GET_TZINFO() ,用于訪問 datetime.datetimedatetime.time 對象的 tzinfo 屬性。 (由 Zackery Spytz 貢獻于 bpo-30155

  • 加入 PyCodec_Unregister() 函數(shù),用于注銷編解碼器檢索函數(shù)。(由 Hai Shi 貢獻于 bpo-41842

  • 加入 PyIter_Send() 函數(shù),可不觸發(fā) StopIteration 異常地向迭代器發(fā)送數(shù)據(jù)。(由 Vladimir Matveev 貢獻于 bpo-41756

  • 受限 C API 中加入了 PyUnicode_AsUTF8AndSize() 。(由 Alex Gaynor 貢獻于 bpo-41784

  • 加入 PyModule_AddObjectRef() 函數(shù):類似于 PyModule_AddObject() 但在成功后不會偷取參數(shù)對象的引用計數(shù)。(由 Victor Stinner 貢獻于 bpo-1635741

  • 加入 Py_NewRef()Py_XNewRef() 函數(shù),用于遞增指定對象的引用計數(shù)并返回該對象。(由 Victor Stinner 貢獻于 bpo-42262

  • 現(xiàn)在, PyType_FromSpecWithBases()PyType_FromModuleAndSpec() 函數(shù)可接受一個類作為 bases 參數(shù)。(由 Serhiy Storchaka 貢獻于 bpo-42423

  • PyType_FromModuleAndSpec() 函數(shù)現(xiàn)在接受 NULL tp_doc 槽位。 (由 Hai Shi 在 bpo-41832 中貢獻。)

  • PyType_GetSlot() 函數(shù)現(xiàn)在可以接受 靜態(tài)類型。 (由 Hai Shi 和 Petr Viktorin 在 bpo-41073 中貢獻。)

  • 新增 PySet_CheckExact() 函數(shù)到 C-API 用于檢查一個對象是否是 set 的實例但不是其子類型的實例。 (由 Pablo Galindo 在 bpo-43277 中貢獻。)

  • 增加了 PyErr_SetInterruptEx(),它允許傳入一個信號序號用于進行模擬。 (由 Antoine Pitrou 在 bpo-43356 中貢獻。)

  • 現(xiàn)在,Python 以調(diào)試模式編譯 時也支持受限 C API 的使用了(需先定義 Py_DEBUG 宏)。在受限 C API 中,如果 Python 是以調(diào)試模式編譯的,且 Py_LIMITED_API 宏以 Python 3.10 以上版本為目標,那么現(xiàn)在 Py_INCREF()Py_DECREF() 函數(shù)實現(xiàn)為非透明的函數(shù)調(diào)用,而非直接訪問 PyObject.ob_refcnt 成員。在調(diào)試模式下支持受限 C API 成為可能,是因為自 Python 3.8 起 PyObject 結構體在發(fā)布模式和調(diào)試模式下是相同的(參見 bpo-36465 )。

    --with-trace-refs 特殊編譯方式下(Py_TRACE_REFS 宏),仍不支持使用受限 C API 。(由 Victor Stinner 貢獻于 bpo-43688

  • 加入 Py_Is(x, y) 函數(shù),用于測試 x 對象是否是 y 對象,等價于 Python 中的 x is y。還加入了 Py_IsNone() 、 Py_IsTrue() 、 Py_IsFalse() 函數(shù),分別用于測試某對象是否為 None 單例、True 單例或 False 單例。(由 Victor Stinner 貢獻于 bpo-43753

  • 新增由 C 代碼控制垃圾回收器的函數(shù): PyGC_Enable(), 、PyGC_Disable() 、 PyGC_IsEnabled()。這些函數(shù)允許從 C 代碼激活、停止和查詢垃圾回收器的狀態(tài),而不必導入 gc 模塊。

  • 新增 Py_TPFLAGS_DISALLOW_INSTANTIATION 類型標記,用于禁止創(chuàng)建類型實例。(由 Victor Stinner 貢獻于 bpo-43916

  • 新增 Py_TPFLAGS_IMMUTABLETYPE 類型標記,用于創(chuàng)建不可變類型對象:類型的屬性不可設置或刪除。(由 Victor Stinner 和 Erlend E. Aasland 貢獻于 bpo-43908

移植到 Python 3.10?

  • 現(xiàn)在必須定義 PY_SSIZE_T_CLEAN 才能使用 PyArg_ParseTuple()Py_BuildValue(),該格式會使用 #: es#, et#, s#, u#, y#, z#, U#Z#。 參見 解析參數(shù)和構造值 以及 PEP 353。 (由 Victor Stinner 在 bpo-40943 中貢獻。)

  • 由于 Py_REFCNT() 已改為內(nèi)聯(lián)靜態(tài)函數(shù),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 中貢獻。)

  • 由于歷史原因,曾經(jīng)允許調(diào)用 PyDict_GetItem() 時不帶 GIL 。 現(xiàn)在則不行了。(由 Victor Stinner 貢獻于 bpo-40839

  • 現(xiàn)在, PyUnicode_FromUnicode(NULL, size)PyUnicode_FromStringAndSize(NULL, size) 會引發(fā) DeprecationWarning。 請利用 PyUnicode_New() 獲得不帶初始數(shù)據(jù)的 Unicode 對象。(由 Inada Naoki 貢獻于 bpo-36346

  • 私有結構體 _PyUnicode_Name_CAPI (PyCapsule API unicodedata.ucnhash_CAPI )已被移入內(nèi)部 C API。(由 Victor Stinner 貢獻于 bpo-42157

  • 現(xiàn)在,若是在 Py_Initialize() 之前去調(diào)用(在 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() 不可再用作左值或右值。例如,現(xiàn)在``x = PyList_SET_ITEM(a, b, c)`` 和 PyList_SET_ITEM(a, b, c) = x 會失敗并提示編譯器錯誤。 這可以防止 if (PyList_SET_ITEM (a, b, c) < 0) ... 之類的檢測發(fā)生問題。(由 Zackery Spytz 和 Victor Stinner 貢獻于 bpo-30459

  • 非受限 API 文件 odictobject.h 、 parser_interface.hpicklebufobject.h 、 pyarena.h 、 pyctype.h、 pydebug.h、 pyfpe.hpytime.h 已被移至 Include/cpython 目錄。這些文件不能被直接包含,因為 Python.h 中已包含過了: Include 文件。 如果已被直接包含,請考慮改為包含 Python.h。(由 Nicholas Sim 貢獻于 bpo-35134

  • 請用 Py_TPFLAGS_IMMUTABLETYPE 類型標記來創(chuàng)建不可變對象。 不要依賴 Py_TPFLAGS_HEAPTYPE 來確定類型對象是否可變;請改為檢查是否設置了 Py_TPFLAGS_IMMUTABLETYPE。(由 Victor Stinner 和 Erlend E. Aasland 貢獻于 bpo-43908

  • 未記入文檔的函數(shù) Py_FrozenMain 已從受限 API 中移除。該函數(shù)主要適用于 Python 的定制版。(由 Petr Viktorin 貢獻于 bpo-26241

棄用?

  • 現(xiàn)在 PyUnicode_InternImmortal() 函數(shù)已被棄用,并將在 Python 3.12 中移除:請改用 PyUnicode_InternInPlace()。(由 Victor Stinner 貢獻于 bpo-41692

移除?

  • 移除了 Py_UNICODE_str* 函數(shù),它被用于控制 Py_UNICODE* 字符串。 (由 Inada Naoki 在 bpo-41123 中貢獻。)

  • 移除了 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_RECURSIONPy_END_ALLOW_RECURSION 以及 PyInterpreterState 結構體的 recursion_critical 字段。 (由 Serhiy Storchaka 在 bpo-41936 中貢獻。)

  • 移除了未記入文檔的 PyOS_InitInterrupts() 函數(shù)。Python 初始化時已隱式安裝了信號處理 handler:參見 PyConfig.install_signal_handlers。(由 Victor Stinner 貢獻于 bpo-41713

  • 移除了 PyAST_Validate() 函數(shù)。不能再使用公有 C API 來構建 AST 對象(mod_ty 類型)了。該函數(shù)已不屬于受限 C API(PEP 384 )。(由 Victor Stinner 貢獻于 bpo-43244

  • 移除了 symtable.h 頭文件及未寫入文檔的函數(shù):

    • PyST_GetScope()

    • PySymtable_Build()

    • PySymtable_BuildObject()

    • PySymtable_Free()

    • Py_SymtableString()

    • Py_SymtableStringObject()

    Py_SymtableString() 函數(shù)誤為穩(wěn)定版 ABI 卻無法使用,因為 symtable.h 頭文件不屬于受限 C API。

    請改用 Python symtable 模塊。 (由 Victor Stinner 在 bpo-43244 中貢獻。)

  • PyOS_ReadlineFunctionPointer() 已從受限 C API 頭文件和 python3.dll 中移除,此 dll 為 Windows 中的穩(wěn)定版 ABI 庫。由于該函數(shù)可接受一個 FILE* 參數(shù),所以無法保證其 ABI 穩(wěn)定性。(由 Petr Viktorin 貢獻于 bpo-43868

  • 移除了 ast.h, asdl.hPython-ast.h 頭文件。 這些函數(shù)未入文檔且不屬于受限 C API。這些頭文件中定義的大多數(shù)名稱都不帶 Py 前綴,因此可能會造成命名沖突。比如 Python-ast.h 定義了一個 Yield 宏,就會與另一個Windows <winbase.h> 頭文件中的 Yield 沖突。請改用 Python ast 模塊。(由 Victor Stinner 貢獻于 bpo-43244

  • 移除了用到 struct _mod 類型的編譯器和解析器函數(shù),因為公共的 AST C API 已被移除:

    • PyAST_Compile()

    • PyAST_CompileEx()

    • PyAST_CompileObject()

    • PyFuture_FromAST()

    • PyFuture_FromASTObject()

    • PyParser_ASTFromFile()

    • PyParser_ASTFromFileObject()

    • PyParser_ASTFromFilename()

    • PyParser_ASTFromString()

    • PyParser_ASTFromStringObject()

    這些函數(shù)未入文檔且不屬于受限 C API。(由 Victor Stinner 貢獻于 bpo-43244

  • 移除了包含下列函數(shù)的頭文件 pyarena.h

    • PyArena_New()

    • PyArena_Free()

    • PyArena_Malloc()

    • PyArena_AddPyObject()

    這些函數(shù)未記入文檔,且不屬于受限 C API,僅由編譯器內(nèi)部使用。(由 Victor Stinner 貢獻于 bpo-43244

  • The PyThreadState.use_tracing member has been removed to optimize Python. (Contributed by Mark Shannon in bpo-43760.)