Python 3.12 的新功能

編輯::

Adam Turner

本文解釋了 Python 3.12 中相對於 3.11 的新功能。Python 3.12 於 2023 年 10 月 2 日釋出。有關完整詳細資訊,請參閱更改日誌

另請參閱

PEP 693 – Python 3.12 釋出時間表

摘要 – 版本亮點

Python 3.12 是 Python 程式語言的穩定版本,對語言和標準庫進行了一些更改。庫的更改側重於清理已棄用的 API、可用性和正確性。值得注意的是,distutils 包已從標準庫中刪除。ospathlib 中的檔案系統支援進行了一些改進,並且一些模組具有更好的效能。

語言更改側重於可用性,因為 f-字串 刪除了許多限制,“你的意思是……”的建議不斷改進。新的型別引數語法type語句提高了使用泛型型別類型別名以及靜態型別檢查器的人體工程學。

本文不嘗試提供所有新功能的完整規範,而是提供方便的概述。有關完整詳細資訊,您應該參考文件,例如庫參考語言參考。如果您想了解更改的完整實現和設計原理,請參閱特定新功能的 PEP;但請注意,一旦功能完全實現,PEP 通常不會保持最新。


新的語法功能

新的語法功能

直譯器改進

Python 資料模型改進

標準庫的重大改進

安全改進

  • hashlib 的內建 SHA1、SHA3、SHA2-384、SHA2-512 和 MD5 實現替換為來自 HACL* 專案的形式驗證程式碼。這些內建實現仍然是後備方案,僅在 OpenSSL 不提供它們時使用。

C API 改進

CPython 實現改進

  • PEP 709,推導式內聯

  • Linux perf 分析器的CPython 支援

  • 在受支援的平臺上實現堆疊溢位保護

新的型別功能

重要的棄用、刪除或限制

  • PEP 623:從 Python C API 中的 Unicode 物件中刪除 wstr,從而使每個 str 物件的大小至少減少 8 個位元組。

  • PEP 632: 移除 distutils 包。 請參閱 遷移指南,以獲取替換其提供的 API 的建議。 如果你仍然需要在 Python 3.12 及更高版本中使用 distutils,第三方 Setuptools 包會繼續提供該模組。

  • gh-95299: 在使用 venv 建立的虛擬環境中,不再預安裝 setuptools。 這意味著 distutilssetuptoolspkg_resourceseasy_install 將不再預設可用;要訪問這些,請在已啟用的虛擬環境中執行 pip install setuptools

  • asynchatasyncoreimp 模組已被移除,同時還有幾個 unittest.TestCase 方法別名

新特性

PEP 695:型別引數語法

PEP 484 下,泛型類和函式使用冗長的語法宣告,這使得型別引數的作用域不明確,並且需要顯式宣告變異性。

PEP 695 引入了一種新的、更緊湊和明確的方式來建立 泛型類函式

def max[T](args: Iterable[T]) -> T:
    ...

class list[T]:
    def __getitem__(self, index: int, /) -> T:
        ...

    def append(self, element: T) -> None:
        ...

此外,PEP 還引入了一種使用 type 語句宣告 類型別名 的新方法,該語句建立 TypeAliasType 的例項

type Point = tuple[float, float]

類型別名也可以是 泛型的

type Point[T] = tuple[T, T]

新語法允許宣告 TypeVarTupleParamSpec 引數,以及具有邊界或約束的 TypeVar 引數

type IntFunc[**P] = Callable[P, int]  # ParamSpec
type LabeledTuple[*Ts] = tuple[str, *Ts]  # TypeVarTuple
type HashableSequence[T: Hashable] = Sequence[T]  # TypeVar with bound
type IntOrStrSequence[T: (int, str)] = Sequence[T]  # TypeVar with constraints

透過此語法建立的類型別名的值以及型別變數的邊界和約束僅在需要時進行評估(請參閱 延遲求值)。這意味著類型別名能夠引用檔案中稍後定義的其他型別。

透過型別引數列表宣告的型別引數在宣告的作用域和任何巢狀作用域內可見,但在外部作用域中不可見。例如,它們可以用於泛型類的方法的型別註釋或類主體中。但是,它們不能在類定義後的模組作用域中使用。有關型別引數的執行時語義的詳細描述,請參閱 型別引數列表

為了支援這些作用域語義,引入了一種新的作用域,即 註解作用域。註解作用域在大多數情況下與函式作用域的行為類似,但在與封閉的類作用域互動時會有所不同。在 Python 3.13 中,註解 也將在註解作用域中進行評估。

有關更多詳細資訊,請參閱 PEP 695

(PEP 由 Eric Traut 編寫。由 Jelle Zijlstra、Eric Traut 和其他人在 gh-103764 中實現。)

PEP 701:f-字串的句法形式化

PEP 701 取消了對 f-字串 使用的一些限制。f-字串內部的表示式元件現在可以是任何有效的 Python 表示式,包括重用與包含 f-字串相同的引號的字串、多行表示式、註釋、反斜槓和 Unicode 轉義序列。讓我們詳細介紹這些

  • 引號重用:在 Python 3.11 中,重用與封閉 f-字串相同的引號會引發 SyntaxError,迫使使用者要麼使用其他可用引號(例如,如果 f-字串使用單引號,則使用雙引號或三引號)。在 Python 3.12 中,你現在可以執行以下操作

    >>> songs = ['Take me back to Eden', 'Alkaline', 'Ascensionism']
    >>> f"This is the playlist: {", ".join(songs)}"
    'This is the playlist: Take me back to Eden, Alkaline, Ascensionism'
    

    請注意,在此更改之前,f-字串的巢狀方式沒有明確的限制,但事實上,字串引號不能在 f-字串的表示式元件內部重用,這使得任意巢狀 f-字串變得不可能。事實上,這是可以編寫的最巢狀的 f-字串

    >>> f"""{f'''{f'{f"{1+1}"}'}'''}"""
    '2'
    

    由於現在 f-字串可以在表示式元件內部包含任何有效的 Python 表示式,因此現在可以任意巢狀 f-字串

    >>> f"{f"{f"{f"{f"{f"{1+1}"}"}"}"}"}"
    '2'
    
  • 多行表示式和註釋:在 Python 3.11 中,f-字串表示式必須在單行中定義,即使 f-字串中的表示式通常可以跨越多行(例如,在多行上定義的文字列表),這使得它們更難閱讀。在 Python 3.12 中,你現在可以定義跨越多行的 f-字串,並新增內聯註釋

    >>> f"This is the playlist: {", ".join([
    ...     'Take me back to Eden',  # My, my, those eyes like fire
    ...     'Alkaline',              # Not acid nor alkaline
    ...     'Ascensionism'           # Take to the broken skies at last
    ... ])}"
    'This is the playlist: Take me back to Eden, Alkaline, Ascensionism'
    
  • 反斜槓和 Unicode 字元:在 Python 3.12 之前,f-字串表示式不能包含任何 \ 字元。這也影響了 Unicode 轉義序列(例如 \N{snowman}),因為這些序列包含之前不能作為 f-字串表示式元件一部分的 \N 部分。現在,你可以定義如下的表示式

    >>> print(f"This is the playlist: {"\n".join(songs)}")
    This is the playlist: Take me back to Eden
    Alkaline
    Ascensionism
    >>> print(f"This is the playlist: {"\N{BLACK HEART SUIT}".join(songs)}")
    This is the playlist: Take me back to Eden♥Alkaline♥Ascensionism
    

有關更多詳細資訊,請參閱 PEP 701

作為此功能實現方式的積極副作用(透過 PEG 解析器 解析 f-字串),現在 f-字串的錯誤訊息更加精確,幷包含錯誤的精確位置。例如,在 Python 3.11 中,以下 f-字串引發 SyntaxError

>>> my_string = f"{x z y}" + f"{1 + 1}"
  File "<stdin>", line 1
    (x z y)
     ^^^
SyntaxError: f-string: invalid syntax. Perhaps you forgot a comma?

但是錯誤訊息不包含行內錯誤的精確位置,並且還人為地用括號括住了表示式。在 Python 3.12 中,由於 f-字串是透過 PEG 解析器解析的,因此錯誤訊息可以更加精確,並顯示整行

>>> my_string = f"{x z y}" + f"{1 + 1}"
  File "<stdin>", line 1
    my_string = f"{x z y}" + f"{1 + 1}"
                   ^^^
SyntaxError: invalid syntax. Perhaps you forgot a comma?

(由 Pablo Galindo、Batuhan Taskaya、Lysandros Nikolaou、Cristián Maureira-Fredes 和 Marta Gómez 在 gh-102856 中貢獻。PEP 由 Pablo Galindo、Batuhan Taskaya、Lysandros Nikolaou 和 Marta Gómez 編寫。)

PEP 684:每個直譯器的 GIL

PEP 684 引入了每個直譯器的 GIL,以便現在可以為每個直譯器建立一個具有唯一 GIL 的子直譯器。這允許 Python 程式充分利用多核 CPU。這目前僅透過 C-API 提供,但預計 Python API 將在 3.13 中推出

使用新的 Py_NewInterpreterFromConfig() 函式建立具有自己 GIL 的直譯器

PyInterpreterConfig config = {
    .check_multi_interp_extensions = 1,
    .gil = PyInterpreterConfig_OWN_GIL,
};
PyThreadState *tstate = NULL;
PyStatus status = Py_NewInterpreterFromConfig(&tstate, &config);
if (PyStatus_Exception(status)) {
    return -1;
}
/* The new interpreter is now active in the current thread. */

有關如何使用 C-API 為具有每個直譯器 GIL 的子直譯器的更多示例,請參閱 Modules/_xxsubinterpretersmodule.c

(由 Eric Snow 在 gh-104210 等中貢獻。)

PEP 669:CPython 的低影響監控

PEP 669 定義了一個新的 API,用於分析器、偵錯程式和其他工具來監控 CPython 中的事件。它涵蓋了廣泛的事件,包括呼叫、返回、行、異常、跳轉等等。這意味著您只需為您使用的部分付費,為近零開銷的偵錯程式和覆蓋率工具提供支援。有關詳細資訊,請參閱 sys.monitoring

(由 Mark Shannon 在 gh-103082 中貢獻。)

PEP 688: 使緩衝區協議可在 Python 中訪問

PEP 688 引入了一種從 Python 程式碼中使用緩衝區協議的方法。實現 __buffer__() 方法的類現在可以用作緩衝區型別。

新的 collections.abc.Buffer ABC 提供了一種表示緩衝區物件的標準方法,例如在型別註釋中。新的 inspect.BufferFlags 列舉表示可用於自定義緩衝區建立的標誌。(由 Jelle Zijlstra 在 gh-102500 中貢獻。)

PEP 709: 推導式內聯

字典、列表和集合推導式現在是內聯的,而不是為每次推導式的執行建立一個新的單次使用函式物件。這使得推導式的執行速度提高了兩倍。有關詳細資訊,請參閱 PEP 709

推導式的迭代變數仍然是隔離的,不會覆蓋外部作用域中同名的變數,也不會在推導式之後可見。內聯確實導致了一些可見的行為變化。

  • 回溯中不再有推導式的單獨幀,並且跟蹤/分析不再將推導式顯示為函式呼叫。

  • symtable 模組將不再為每個推導式生成子符號表;相反,推導式的區域性變數將包含在父函式的符號表中。

  • 在推導式內部呼叫 locals() 現在包括來自推導式外部的變數,並且不再包括推導式“引數”的合成 .0 變數。

  • 當在跟蹤(例如程式碼覆蓋率測量)下執行時,直接迭代 locals() 的推導式(例如 [k for k in locals()])可能會看到 “RuntimeError: dictionary changed size during iteration”。這與在例如 for k in locals(): 中看到的行為相同。要避免此錯誤,請先建立一個要迭代的鍵列表:keys = list(locals()); [k for k in keys]

(由 Carl Meyer 和 Vladimir Matveev 在 PEP 709 中貢獻。)

改進的錯誤訊息

  • 現在,當 NameError 引發到頂層時,直譯器顯示的錯誤訊息中可能會建議標準庫中的模組。(由 Pablo Galindo 在 gh-98254 中貢獻。)

    >>> sys.version_info
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    NameError: name 'sys' is not defined. Did you forget to import 'sys'?
    
  • 改進例項的 NameError 異常的錯誤建議。現在,如果在一個方法中引發 NameError,並且該例項的屬性與異常中的名稱完全相等,則建議將包括 self.<NAME>,而不是方法範圍內的最接近的匹配項。(由 Pablo Galindo 在 gh-99139 中貢獻。)

    >>> class A:
    ...    def __init__(self):
    ...        self.blech = 1
    ...
    ...    def foo(self):
    ...        somethin = blech
    ...
    >>> A().foo()
    Traceback (most recent call last):
      File "<stdin>", line 1
        somethin = blech
                   ^^^^^
    NameError: name 'blech' is not defined. Did you mean: 'self.blech'?
    
  • 當用戶鍵入 import x from y 而不是 from y import x 時,改進 SyntaxError 錯誤訊息。(由 Pablo Galindo 在 gh-98931 中貢獻。)

    >>> import a.y.z from b.y.z
    Traceback (most recent call last):
      File "<stdin>", line 1
        import a.y.z from b.y.z
        ^^^^^^^^^^^^^^^^^^^^^^^
    SyntaxError: Did you mean to use 'from ... import ...' instead?
    
  • 從失敗的 from <module> import <name> 語句引發的 ImportError 異常現在包括基於 <module> 中的可用名稱的 <name> 值的建議。(由 Pablo Galindo 在 gh-91058 中貢獻。)

    >>> from collections import chainmap
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    ImportError: cannot import name 'chainmap' from 'collections'. Did you mean: 'ChainMap'?
    

其他語言更改

  • 現在,當解析包含空位元組的原始碼時,解析器會引發 SyntaxError。(由 Pablo Galindo 在 gh-96670 中貢獻。)

  • 現在,不是有效的轉義序列的反斜槓字元對會生成 SyntaxWarning,而不是 DeprecationWarning。例如,re.compile("\d+\.\d+") 現在會發出一個 SyntaxWarning"\d" 是無效的轉義序列,對正則表示式使用原始字串:re.compile(r"\d+\.\d+"))。在未來的 Python 版本中,最終將引發 SyntaxError,而不是 SyntaxWarning。(由 Victor Stinner 在 gh-98401 中貢獻。)

  • 八進位制轉義符的值大於 0o377 (例如:"\477"),在 Python 3.11 中已被棄用,現在會產生一個 SyntaxWarning,而不是 DeprecationWarning。在未來的 Python 版本中,它們最終會成為一個 SyntaxError。(由 Victor Stinner 在 gh-98401 中貢獻。)

  • 在推導式目標部分中使用的、未儲存的變數現在可以在賦值表示式中使用(:=)。例如,在 [(b := 1) for a, b.prop in some_iter] 中,現在允許對 b 進行賦值。請注意,按照 PEP 572 的規定,仍然不允許對推導式目標部分中儲存的變數進行賦值(如 a)。(由 Nikita Sobolev 在 gh-100581 中貢獻。)

  • 在類或型別的 __set_name__ 方法中引發的異常不再被 RuntimeError 包裹。上下文資訊會作為 PEP 678 註釋新增到異常中。(由 Irit Katriel 在 gh-77757 中貢獻。)

  • try-except* 結構處理整個 ExceptionGroup 並引發另一個異常時,該異常不再被包裹在 ExceptionGroup 中。此項更改也出現在 3.11.4 版本中。(由 Irit Katriel 在 gh-103590 中貢獻。)

  • 垃圾回收器現在僅在 Python 位元組碼評估迴圈的 eval 斷路器機制上執行,而不是在物件分配時執行。當呼叫 PyErr_CheckSignals() 時,GC 也可以執行,因此需要長時間執行而不執行任何 Python 程式碼的 C 擴充套件也有機會定期執行 GC。(由 Pablo Galindo 在 gh-97922 中貢獻。)

  • 所有期望布林引數的內建函式和擴充套件函式現在接受任何型別的引數,而不僅僅是 boolint。(由 Serhiy Storchaka 在 gh-60203 中貢獻。)

  • memoryview 現在支援半精度浮點型別(“e” 格式程式碼)。(由 Donghee Na 和 Antoine Pitrou 在 gh-90751 中貢獻。)

  • slice 物件現在是可雜湊的,允許它們用作字典鍵和集合項。(由 Will Bradshaw、Furkan Onder 和 Raymond Hettinger 在 gh-101264 中貢獻。)

  • sum() 現在使用 Neumaier 求和來提高對浮點數或混合整數和浮點數求和時的準確性和交換性。(由 Raymond Hettinger 在 gh-100425 中貢獻。)

  • 當解析包含空位元組的原始碼時,ast.parse() 現在會引發 SyntaxError,而不是 ValueError。(由 Pablo Galindo 在 gh-96670 中貢獻。)

  • tarfile 中的提取方法和 shutil.unpack_archive() 有一個新的 *filter* 引數,允許限制可能令人驚訝或危險的 tar 功能,例如在目標目錄之外建立檔案。有關詳細資訊,請參閱 tarfile 提取過濾器。在 Python 3.14 中,預設值將切換為 'data'。(由 Petr Viktorin 在 PEP 706 中貢獻。)

  • 如果底層對映是可雜湊的,則 types.MappingProxyType 例項現在是可雜湊的。(由 Serhiy Storchaka 在 gh-87995 中貢獻。)

  • 透過新的環境變數 PYTHONPERFSUPPORT 和命令列選項 -X perf 以及新的 sys.activate_stack_trampoline()sys.deactivate_stack_trampoline()sys.is_stack_trampoline_active() 函式,添加了 對 perf profiler 的支援。(由 Pablo Galindo 設計。由 Pablo Galindo 和 Christian Heimes 貢獻,並得到 Gregory P. Smith [Google] 和 Mark Shannon 在 gh-96123 中的貢獻。)

新模組

  • 無。

改進的模組

array

asyncio

日曆

csv

dis

  • 偽指令操作碼(由編譯器使用但不出現在可執行位元組碼中)現在在 dis 模組中公開。HAVE_ARGUMENT 仍然與實際操作碼相關,但它對於偽指令沒有用。請改用新的 dis.hasarg 集合。(由 Irit Katriel 在 gh-94216 中貢獻。)

  • 添加了 dis.hasexc 集合,以表示設定異常處理程式的指令。(由 Irit Katriel 在 gh-94216 中貢獻。)

fractions

importlib.resources

inspect

itertools

  • 添加了 itertools.batched(),用於收集到大小均勻的元組中,其中最後一個批次可能比其餘的短。(由 Raymond Hettinger 在 gh-98363 中貢獻。)

math

  • 添加了 math.sumprod(),用於計算乘積之和。(由 Raymond Hettinger 在 gh-100485 中貢獻。)

  • 擴充套件了 math.nextafter() 以包括 steps 引數,用於一次向上或向下移動多個步驟。(由 Matthias Goergens、Mark Dickinson 和 Raymond Hettinger 在 gh-94906 中貢獻。)

os

  • 添加了 os.PIDFD_NONBLOCK,用於在非阻塞模式下使用 os.pidfd_open() 為程序開啟檔案描述符。(由 Kumar Aditya 在 gh-93312 中貢獻。)

  • 現在,os.DirEntry 包括 os.DirEntry.is_junction() 方法,用於檢查條目是否為連線點。(由 Charles Machalow 在 gh-99547 中貢獻。)

  • 在 Windows 上添加了 os.listdrives()os.listvolumes()os.listmounts() 函式,用於列舉驅動器、卷和掛載點。(由 Steve Dower 在 gh-102519 中貢獻。)

  • 現在,os.stat()os.lstat() 在 Windows 上更加準確。st_birthtime 欄位現在將填充檔案的建立時間,並且 st_ctime 已棄用,但仍然包含建立時間(但將來將返回最後一次元資料更改,以與其他平臺保持一致)。st_dev 可能最多為 64 位,st_ino 可能最多為 128 位,具體取決於您的檔案系統,並且 st_rdev 始終設定為零而不是不正確的值。這兩個函式在新版本的 Windows 上可能會明顯更快。(由 Steve Dower 在 gh-99726 中貢獻。)

os.path

pathlib

pdb

  • 新增方便的變數以臨時儲存除錯會話的值,並提供對當前幀或返回值等值的快速訪問。(由 Tian Gao 在 gh-103693 中貢獻。)

random

shutil

  • shutil.make_archive() 現在將 root_dir 引數傳遞給支援它的自定義歸檔器。在這種情況下,它不再臨時將程序的當前工作目錄更改為 root_dir 來執行歸檔。(由 Serhiy Storchaka 在 gh-74696 中貢獻。)

  • shutil.rmtree() 現在接受一個新引數 onexc,它是一個錯誤處理程式,類似於 onerror,但期望的是一個異常例項而不是 (typ, val, tb) 三元組。onerror 已被棄用。(由 Irit Katriel 在 gh-102828 中貢獻。)

  • shutil.which() 現在會查詢 PATHEXT 環境變數,以便在 Windows 上即使給定的 cmd 包含目錄元件時,也能在 PATH 中找到匹配項。(由 Charles Machalow 在 gh-103179 中貢獻。)

    shutil.which() 在 Windows 上查詢可執行檔案時,將呼叫 NeedCurrentDirectoryForExePathW,以確定當前工作目錄是否應新增到搜尋路徑中。(由 Charles Machalow 在 gh-103179 中貢獻。)

    shutil.which() 將返回一個與 cmd 匹配的路徑,該路徑在 Windows 上從搜尋路徑的其他直接匹配之前,包含來自 PATHEXT 的元件。(由 Charles Machalow 在 gh-103179 中貢獻。)

sqlite3

statistics

  • 擴充套件 statistics.correlation(),使其包含一個 ranked 方法,用於計算排名資料的 Spearman 相關性。(由 Raymond Hettinger 在 gh-95861 中貢獻。)

sys

tempfile

threading

tkinter

  • tkinter.Canvas.coords() 現在扁平化其引數。它現在不僅接受座標作為單獨的引數 (x1, y1, x2, y2, ...) 和座標序列 ([x1, y1, x2, y2, ...]),還接受成對分組的座標 ((x1, y1), (x2, y2), ...[(x1, y1), (x2, y2), ...]),例如 create_*() 方法。(由 Serhiy Storchaka 在 gh-94473 中貢獻。)

tokenize

types

typing

  • 針對 執行時可檢查協議isinstance() 檢查現在使用 inspect.getattr_static() 而不是 hasattr() 來查詢屬性是否存在。這意味著在針對執行時可檢查協議進行 isinstance() 檢查期間,描述符和 __getattr__() 方法將不再被意外評估。 但是,這也可能意味著某些曾經被認為是執行時可檢查協議的例項的物件可能不再被視為 Python 3.12+ 上該協議的例項,反之亦然。 大多數使用者不太可能受到此更改的影響。(由 Alex Waygood 在 gh-102433 中貢獻。)

  • 執行時可檢查協議的成員現在在建立類後立即被視為在執行時“凍結”。將屬性修補到執行時可檢查協議上仍然有效,但不會影響將物件與協議進行比較的 isinstance() 檢查。 例如

    >>> from typing import Protocol, runtime_checkable
    >>> @runtime_checkable
    ... class HasX(Protocol):
    ...     x = 1
    ...
    >>> class Foo: ...
    ...
    >>> f = Foo()
    >>> isinstance(f, HasX)
    False
    >>> f.x = 1
    >>> isinstance(f, HasX)
    True
    >>> HasX.y = 2
    >>> isinstance(f, HasX)  # unchanged, even though HasX now also has a "y" attribute
    True
    

    進行此更改是為了加快針對執行時可檢查協議的 isinstance() 檢查。

  • 針對 執行時可檢查協議isinstance() 檢查的效能配置檔案已發生重大變化。針對只有少數成員的協議進行的 isinstance() 檢查應該至少比 3.11 快 2 倍,有些可能快 20 倍或更多。 但是,針對具有多個成員的協議進行的 isinstance() 檢查可能比 Python 3.11 慢。(由 Alex Waygood 在 gh-74690gh-103193 中貢獻。)

  • 所有 typing.TypedDicttyping.NamedTuple 類現在都有 __orig_bases__ 屬性。(由 Adrian Garcia Badaracco 在 gh-103699 中貢獻。)

  • typing.dataclass_transform() 新增 frozen_default 引數。(由 Erik De Bonte 在 gh-99957 中貢獻。)

unicodedata

  • Unicode 資料庫已更新至 15.0.0 版。(由 Benjamin Peterson 在 gh-96734 中貢獻。)

unittest

新增一個 --durations 命令列選項,顯示 N 個最慢的測試用例

python3 -m unittest --durations=3 lib.tests.test_threading
.....
Slowest test durations
----------------------------------------------------------------------
1.210s     test_timeout (Lib.test.test_threading.BarrierTests)
1.003s     test_default_timeout (Lib.test.test_threading.BarrierTests)
0.518s     test_timeout (Lib.test.test_threading.EventTests)

(0.000 durations hidden.  Use -v to show these durations.)
----------------------------------------------------------------------
Ran 158 tests in 9.869s

OK (skipped=3)

(由 Giampaolo Rodola 在 gh-48330 中貢獻)

uuid

最佳化

  • 從 Unicode 物件中刪除 wstrwstr_length 成員。 這在 64 位平臺上將物件大小減少了 8 或 16 個位元組。 (PEP 623) (由 Inada Naoki 在 gh-92536 中貢獻。)

  • 在構建過程中新增對使用 BOLT 二進位制最佳化器的實驗性支援,這可以將效能提高 1-5%。(由 Kevin Modzelewski 在 gh-90536 中貢獻,並由 Donghee Na 在 gh-101525 中調整。)

  • 將正則表示式替換(函式 re.sub()re.subn() 以及相應的 re.Pattern 方法)的速度提高了 2-3 倍,針對包含組引用的替換字串。(由 Serhiy Storchaka 在 gh-91524 中貢獻。)

  • 透過延遲昂貴的字串格式化來加速 asyncio.Task 的建立。(由 Itamar Oren 在 gh-103793 中貢獻。)

  • 由於需要覆蓋 PEP 701 的更改在 tokenize 模組中,tokenize.tokenize()tokenize.generate_tokens() 函式的速度提高了高達 64%。(由 Marta Gómez Macías 和 Pablo Galindo 在 gh-102856 中貢獻。)

  • 透過新的 LOAD_SUPER_ATTR 指令,加速 super() 方法呼叫和屬性載入。(由 Carl Meyer 和 Vladimir Matveev 在 gh-103497 中貢獻。)

CPython 位元組碼更改

演示和工具

  • 移除包含舊演示指令碼的 Tools/demo/ 目錄。可以在 old-demos 專案中找到副本。(由 Victor Stinner 在 gh-97681 中貢獻。)

  • 移除 Tools/scripts/ 目錄中過時的示例指令碼。可以在 old-demos 專案中找到副本。(由 Victor Stinner 在 gh-97669 中貢獻。)

已棄用

Python 3.13 中待移除的內容

模組(請參閱 PEP 594

  • aifc

  • audioop

  • cgi

  • cgitb

  • chunk

  • crypt

  • imghdr

  • mailcap

  • msilib

  • nis

  • nntplib

  • ossaudiodev

  • pipes

  • sndhdr

  • spwd

  • sunau

  • telnetlib

  • uu

  • xdrlib

其他模組

API

Python 3.14 中待移除的內容

計劃在 Python 3.15 中移除

  • 匯入系統

    • 在未能設定 __spec__.cached 的情況下在模組上設定 __cached__ 已被棄用。 在 Python 3.15 中,匯入系統或標準庫將停止設定或考慮 __cached__。(gh-97879

    • 在未能設定 __spec__.parent 的情況下在模組上設定 __package__ 已被棄用。 在 Python 3.15 中,匯入系統或標準庫將停止設定或考慮 __package__。(gh-97879

  • ctypes:

    • 未文件化的 ctypes.SetPointerType() 函式自 Python 3.13 起已被棄用。

  • http.server:

    • 自 Python 3.13 起,過時且很少使用的 CGIHTTPRequestHandler 已被棄用。 沒有直接的替代品。 任何東西都比 CGI 更好,可以將 Web 伺服器與請求處理程式連線起來。

    • 自 Python 3.13 起,python -m http.server 命令列介面的 --cgi 標誌已被棄用。

  • locale:

  • pathlib:

  • platform:

    • 自 Python 3.13 起,java_ver() 已被棄用。此函式僅對 Jython 支援有用,具有令人困惑的 API,並且基本上未經測試。

  • threading:

    • RLock() 在 Python 3.15 中將不接受任何引數。自 Python 3.14 起,傳遞任何引數都已被棄用,因為 Python 版本不允許任何引數,但 C 版本允許任何數量的位置引數或關鍵字引數,並忽略每個引數。

  • types:

  • typing:

    • 用於建立 NamedTuple 類的未文件化的關鍵字引數語法(例如 Point = NamedTuple("Point", x=int, y=int))自 Python 3.13 起已被棄用。請改用基於類的語法或函式式語法。

    • 自 Python 3.13 起,typing.no_type_check_decorator() 裝飾器函式已被棄用。在 typing 模組中存在八年後,它仍然未被任何主要的型別檢查器支援。

  • wave:

計劃在 Python 3.16 中移除

  • 匯入系統

    • 在未能設定 __spec__.loader 的同時設定模組的 __loader__ 已被棄用。在 Python 3.16 中,匯入系統或標準庫將不再設定或考慮 __loader__

  • array:

    • 自 Python 3.3 起,文件中已棄用 'u' 格式程式碼 (wchar_t),自 Python 3.13 起,執行時已棄用。請改用 'w' 格式程式碼 (Py_UCS4) 來表示 Unicode 字元。

  • asyncio:

  • builtins:

    • 對布林型別進行按位反轉,例如 ~True~False,自 Python 3.12 起已被棄用,因為它會產生令人驚訝且不直觀的結果(-2-1)。對於布林值的邏輯非,請改用 not x。在極少數情況下,如果您需要底層整數的按位反轉,請顯式轉換為 int (~int(x))。

  • shutil:

    • 自 Python 3.14 起,ExecError 異常已被棄用。自 Python 3.4 以來,shutil 中的任何函式都沒有使用它,現在它是 RuntimeError 的別名。

  • symtable:

  • sys:

  • tarfile:

    • 自 Python 3.13 起,未文件化且未使用的 TarFile.tarfile 屬性已被棄用。

計劃在未來版本中移除

以下 API 將在未來刪除,但目前尚未安排刪除日期。

  • argparse:巢狀引數組和巢狀互斥組已被棄用。

  • array'u' 格式程式碼 (gh-57281)

  • builtins:

    • bool(NotImplemented).

    • 生成器: throw(type, exc, tb)athrow(type, exc, tb) 簽名已棄用:請改用 throw(exc)athrow(exc),即單引數簽名。

    • 目前,Python 允許數字字面量緊跟關鍵字,例如 0in x1or x0if 1else 2。這允許出現令人困惑和模稜兩可的表示式,如 [0x1for x in y] (可以解釋為 [0x1 for x in y][0x1f or x in y])。如果數字字面量緊跟以下關鍵字之一,則會引發語法警告:andelseforifinisor。在未來的版本中,這將改為語法錯誤。(gh-87999

    • 支援 __index__()__int__() 方法返回非 int 型別:這些方法將需要返回 int 的嚴格子類的例項。

    • 支援 __float__() 方法返回 float 的嚴格子類:這些方法將需要返回 float 的例項。

    • 支援 __complex__() 方法返回 complex 的嚴格子類:這些方法將需要返回 complex 的例項。

    • int() 的呼叫委託給 __trunc__() 方法。

    • 現在不建議將複數作為 complex() 建構函式中的 *real* 或 *imag* 引數傳遞;它應該只作為單個位置引數傳遞。(由 Serhiy Storchaka 在 gh-109218 中貢獻。)

  • calendarcalendar.Januarycalendar.February 常量已棄用,並由 calendar.JANUARYcalendar.FEBRUARY 替代。(由 Prince Roshan 在 gh-103636 中貢獻。)

  • codeobject.co_lnotab:請使用 codeobject.co_lines() 方法代替。

  • datetime:

    • utcnow():請使用 datetime.datetime.now(tz=datetime.UTC)

    • utcfromtimestamp():請使用 datetime.datetime.fromtimestamp(timestamp, tz=datetime.UTC)

  • gettext:複數形式的值必須是整數。

  • importlib:

    • load_module() 方法:請使用 exec_module() 代替。

    • cache_from_source() 的 *debug_override* 引數已棄用:請使用 *optimization* 引數代替。

  • importlib.metadata:

    • EntryPoints 元組介面。

    • 返回值上的隱式 None

  • loggingwarn() 方法自 Python 3.3 起已被棄用,請使用 warning() 代替。

  • mailbox:不推薦使用 StringIO 輸入和文字模式,請使用 BytesIO 和二進位制模式代替。

  • os:在多執行緒程序中呼叫 os.register_at_fork()

  • pydoc.ErrorDuringImport:*exc_info* 引數的元組值已棄用,請使用異常例項。

  • re:正則表示式中的數字組引用和組名現在應用更嚴格的規則。現在只接受 ASCII 數字序列作為數字引用。位元組模式和替換字串中的組名現在只能包含 ASCII 字母、數字和下劃線。(由 Serhiy Storchaka 在 gh-91760 中貢獻。)

  • sre_compilesre_constantssre_parse 模組。

  • shutilrmtree() 的 *onerror* 引數在 Python 3.12 中已棄用;請使用 *onexc* 引數代替。

  • ssl 選項和協議

    • 不帶 protocol 引數的 ssl.SSLContext 已棄用。

    • ssl.SSLContextset_npn_protocols()selected_npn_protocol() 已棄用:請使用 ALPN 代替。

    • ssl.OP_NO_SSL* 選項

    • ssl.OP_NO_TLS* 選項

    • ssl.PROTOCOL_SSLv3

    • ssl.PROTOCOL_TLS

    • ssl.PROTOCOL_TLSv1

    • ssl.PROTOCOL_TLSv1_1

    • ssl.PROTOCOL_TLSv1_2

    • ssl.TLSVersion.SSLv3

    • ssl.TLSVersion.TLSv1

    • ssl.TLSVersion.TLSv1_1

  • sysconfig.is_python_build() 的 *check_home* 引數已棄用並被忽略。

  • threading 方法

  • typing.Text (gh-92332)。

  • unittest.IsolatedAsyncioTestCase:從測試用例返回值(不是 None)已棄用。

  • urllib.parse 中已棄用的函式:請使用 urlparse() 代替。

    • splitattr()

    • splithost()

    • splitnport()

    • splitpasswd()

    • splitport()

    • splitquery()

    • splittag()

    • splittype()

    • splituser()

    • splitvalue()

    • to_bytes()

  • urllib.request:呼叫請求的 URLopenerFancyURLopener 樣式已被棄用。請使用較新的 urlopen() 函式和方法。

  • wsgirefSimpleHandler.stdout.write() 不應進行部分寫入。

  • xml.etree.ElementTree:測試 Element 的真值已被棄用。在未來的版本中,它將始終返回 True。請首選顯式的 len(elem)elem is not None 測試。

  • zipimport.zipimporter.load_module() 已被棄用:請改用 exec_module()

已移除

asynchat 和 asyncore

  • 這兩個模組已按照 PEP 594 中的時間表移除,它們在 Python 3.6 中已被棄用。請改用 asyncio。(由 Nikita Sobolev 在 gh-96580 中貢獻。)

configparser

distutils

  • 移除 distutils 包。它在 Python 3.10 中被 PEP 632 “棄用 distutils 模組”棄用。對於仍在使用 distutils 且無法更新為其他內容的專案,可以安裝 setuptools 專案:它仍然提供 distutils。(由 Victor Stinner 在 gh-92584 中貢獻。)

ensurepip

  • ensurepip 中刪除捆綁的 setuptools wheel,並停止在由 venv 建立的環境中安裝 setuptools。

    pip (>= 22.1) 不需要在環境中安裝 setuptools。setuptools 基(和 distutils 基)的包仍然可以與 pip install 一起使用,因為 pip 將在其用於構建包的構建環境中提供 setuptools

    easy_installpkg_resourcessetuptoolsdistutils 不再預設在由 venv 建立或由 ensurepip 引導的環境中提供,因為它們是 setuptools 包的一部分。對於在執行時依賴這些的專案,應將 setuptools 專案宣告為依賴項並單獨安裝(通常使用 pip)。

    (由 Pradyun Gedam 在 gh-95299 中貢獻。)

enum

  • 移除 enumEnumMeta.__getattr__,列舉屬性訪問不再需要它。(由 Ethan Furman 在 gh-95083 中貢獻。)

ftplib

  • 移除 ftplibFTP_TLS.ssl_version 類屬性:請改用 *context* 引數。(由 Victor Stinner 在 gh-94172 中貢獻。)

gzip

  • 移除 gzipgzip.GzipFilefilename 屬性,該屬性自 Python 2.6 起已被棄用,請改用 name 屬性。在寫入模式下,如果不存在,filename 屬性會新增 '.gz' 副檔名。(由 Victor Stinner 在 gh-94196 中貢獻。)

hashlib

  • 移除 hashlibhashlib.pbkdf2_hmac() 的純 Python 實現,該實現在 Python 3.10 中已被棄用。Python 3.10 及更高版本需要 OpenSSL 1.1.1 (PEP 644):此 OpenSSL 版本提供了 pbkdf2_hmac() 的 C 實現,速度更快。(由 Victor Stinner 在 gh-94199 中貢獻。)

importlib

  • 現在已完成 importlib 中許多先前已棄用的清理工作

    • 已移除對 module_repr() 的引用和支援。(由 Barry Warsaw 在 gh-97850 中貢獻。)

    • importlib.util.set_packageimportlib.util.set_loaderimportlib.util.module_for_loader 已全部移除。(由 Brett Cannon 和 Nikita Sobolev 在 gh-65961gh-97850 中貢獻。)

    • 已移除對 find_loader()find_module() API 的支援。(由 Barry Warsaw 在 gh-98040 中貢獻。)

    • importlib.abc.Finderpkgutil.ImpImporterpkgutil.ImpLoader 已被移除。(由 Barry Warsaw 在 gh-98040 中貢獻。)

imp

  • imp 模組已被移除。(由 Barry Warsaw 在 gh-98040 中貢獻。)

    要進行遷移,請查閱以下對應表

    imp

    importlib

    imp.NullImporter

    None 插入到 sys.path_importer_cache

    imp.cache_from_source()

    importlib.util.cache_from_source()

    imp.find_module()

    importlib.util.find_spec()

    imp.get_magic()

    importlib.util.MAGIC_NUMBER

    imp.get_suffixes()

    importlib.machinery.SOURCE_SUFFIXESimportlib.machinery.EXTENSION_SUFFIXESimportlib.machinery.BYTECODE_SUFFIXES

    imp.get_tag()

    sys.implementation.cache_tag

    imp.load_module()

    importlib.import_module()

    imp.new_module(name)

    types.ModuleType(name)

    imp.reload()

    importlib.reload()

    imp.source_from_cache()

    importlib.util.source_from_cache()

    imp.load_source()

    見下文

    imp.load_source() 替換為

    import importlib.util
    import importlib.machinery
    
    def load_source(modname, filename):
        loader = importlib.machinery.SourceFileLoader(modname, filename)
        spec = importlib.util.spec_from_file_location(modname, filename, loader=loader)
        module = importlib.util.module_from_spec(spec)
        # The module is always executed and not cached in sys.modules.
        # Uncomment the following line to cache the module.
        # sys.modules[module.__name__] = module
        loader.exec_module(module)
        return module
    
  • 移除沒有替代的 imp 函式和屬性

    • 未文件化的函式

      • imp.init_builtin()

      • imp.load_compiled()

      • imp.load_dynamic()

      • imp.load_package()

    • imp.lock_held()imp.acquire_lock()imp.release_lock():Python 3.3 中鎖定方案已更改為每個模組鎖定。

    • imp.find_module() 常量:SEARCH_ERRORPY_SOURCEPY_COMPILEDC_EXTENSIONPY_RESOURCEPKG_DIRECTORYC_BUILTINPY_FROZENPY_CODERESOURCEIMP_HOOK

io

  • 移除 ioio.OpenWrapper_pyio.OpenWrapper,它們在 Python 3.10 中已棄用:直接使用 open() 即可。open()io.open())函式是一個內建函式。從 Python 3.10 開始,_pyio.open() 也是一個靜態方法。(由 Victor Stinner 在 gh-94169 中貢獻。)

locale

smtpd

  • 根據 PEP 594 中的計劃,smtpd 模組已被移除,它在 Python 3.4.7 和 3.5.4 中已棄用。請改用 aiosmtpd PyPI 模組或任何其他基於 asyncio 的伺服器。(由 Oleg Iarygin 在 gh-93243 中貢獻。)

sqlite3

  • 以下未文件化的 sqlite3 功能在 Python 3.10 中已棄用,現在已被刪除

    • sqlite3.enable_shared_cache()

    • sqlite3.OptimizedUnicode

    如果必須使用共享快取,請使用 cache=shared 查詢引數以 URI 模式開啟資料庫。

    自 Python 3.3 以來,sqlite3.OptimizedUnicode 文字工廠一直是 str 的別名。先前將文字工廠設定為 OptimizedUnicode 的程式碼可以顯式使用 str,或者依賴於預設值,該值也是 str

    (由 Erlend E. Aasland 在 gh-92548 中貢獻。)

ssl

  • 移除 sslssl.RAND_pseudo_bytes() 函式,它在 Python 3.6 中已棄用:請改用 os.urandom()ssl.RAND_bytes()。(由 Victor Stinner 在 gh-94199 中貢獻。)

  • 移除 ssl.match_hostname() 函式。它在 Python 3.7 中已棄用。自 Python 3.7 以來,OpenSSL 執行主機名匹配,Python 不再使用 ssl.match_hostname() 函式。(由 Victor Stinner 在 gh-94199 中貢獻。)

  • 移除 ssl.wrap_socket() 函式,它在 Python 3.7 中已棄用:請改為建立一個 ssl.SSLContext 物件並呼叫其 ssl.SSLContext.wrap_socket 方法。任何仍然使用 ssl.wrap_socket() 的軟體包都是損壞且不安全的。該函式既不傳送 SNI TLS 擴充套件,也不驗證伺服器主機名。程式碼容易受到 CWE 295 (不正確的證書驗證)的影響。(由 Victor Stinner 在 gh-94199 中貢獻。)

unittest

webbrowser

  • webbrowser 中移除對過時瀏覽器的支援。移除的瀏覽器包括:Grail、Mosaic、Netscape、Galeon、Skipstone、Iceape、Firebird 和 35 及以下版本的 Firefox ( gh-102871 )。

xml.etree.ElementTree

  • 移除純 Python 實現的 ElementTree.Element.copy() 方法,該方法在 Python 3.10 中已棄用,請改用 copy.copy() 函式。xml.etree.ElementTree 的 C 實現沒有 copy() 方法,只有一個 __copy__() 方法。(由 Victor Stinner 在 gh-94383 中貢獻。)

zipimport

  • 移除 zipimportfind_loader()find_module() 方法,這兩個方法在 Python 3.10 中已棄用:請改用 find_spec() 方法。有關原理,請參閱 PEP 451。(由 Victor Stinner 在 gh-94379 中貢獻。)

其他

  • 從文件 MakefileDoc/tools/rstlint.py 中刪除 suspicious 規則,這兩個檔案都支援 sphinx-lint。(由 Julien Palard 在 gh-98179 中貢獻。)

  • ftplibimaplibpoplibsmtplib 模組中移除 keyfilecertfile 引數,以及從 http.client 模組中移除 key_filecert_filecheck_hostname 引數,這些引數自 Python 3.6 起已棄用。請改用 context 引數(imaplib 中的 ssl_context)。(由 Victor Stinner 在 gh-94172 中貢獻。)

  • 從多個 stdlib 模組和測試中刪除 Jython 相容性 hack。(由 Nikita Sobolev 在 gh-99482 中貢獻。)

  • ctypes 模組中移除 _use_broken_old_ctypes_structure_semantics_ 標誌。(由 Nikita Sobolev 在 gh-99285 中貢獻。)

移植到 Python 3.12

本節列出了先前描述的更改和其他錯誤修復,這些更改可能需要您修改程式碼。

Python API 中的更改

  • 現在對正則表示式中的數字組引用和組名稱應用了更嚴格的規則。現在只接受 ASCII 數字序列作為數字引用。位元組模式和替換字串中的組名稱現在只能包含 ASCII 字母和數字以及下劃線。(由 Serhiy Storchaka 在 gh-91760 中貢獻。)

  • 移除自 Python 3.10 起已棄用的 randrange() 功能。以前,randrange(10.0) 會無損地轉換為 randrange(10)。現在,它會引發 TypeError。此外,對於非整數值(例如 randrange(10.5)randrange('10'))引發的異常已從 ValueError 更改為 TypeError。這也防止了 randrange(1e25) 會靜默地從比 randrange(10**25) 更大的範圍中進行選擇的錯誤。(最初由 Serhiy Storchaka 建議 gh-86388。)

  • argparse.ArgumentParser 更改了從檔案讀取引數(例如 fromfile_prefix_chars 選項)的編碼和錯誤處理程式,從預設文字編碼(例如 locale.getpreferredencoding(False))更改為 檔案系統編碼和錯誤處理程式。在 Windows 上,引數檔案應使用 UTF-8 而不是 ANSI 內碼表進行編碼。

  • 移除在 Python 3.4.7 和 3.5.4 中已棄用的基於 asyncoresmtpd 模組。推薦的替代方案是基於 asyncioaiosmtpd PyPI 模組。

  • shlex.split():為 s 引數傳遞 None 現在會引發異常,而不是讀取 sys.stdin。該功能在 Python 3.9 中已棄用。(由 Victor Stinner 在 gh-94352 中貢獻。)

  • os 模組不再接受類似位元組的路徑,例如 bytearraymemoryview 型別:對於位元組字串,僅接受精確的 bytes 型別。(由 Victor Stinner 在 gh-98393 中貢獻。)

  • 如果子直譯器中使用 syslog.openlog()syslog.closelog(),現在會失敗。 syslog.syslog() 仍然可以在子直譯器中使用,但前提是必須在主直譯器中先呼叫過 syslog.openlog()。 這些新的限制不適用於主直譯器,因此只有極少數使用者可能會受到影響。 此更改有助於直譯器隔離。 此外,syslog 是對程序全域性資源的包裝,最好從主直譯器進行管理。(由 Donghee Na 在 gh-99127 中貢獻。)

  • cached_property() 未記錄的鎖定行為已被移除,因為它會跨類的所有例項進行鎖定,導致高鎖爭用。 這意味著,如果兩個執行緒競爭,則快取屬性的 getter 函式現在可能會為單個例項執行多次。 對於大多數簡單的快取屬性(例如,那些是冪等且僅根據例項的其他屬性計算值的屬性),這不會有問題。 如果需要同步,請在快取屬性的 getter 函式中或在多執行緒訪問點周圍實現鎖定。

  • sys._current_exceptions() 現在返回一個從執行緒 ID 到異常例項的對映,而不是到一個 (typ, exc, tb) 元組。(由 Irit Katriel 在 gh-103176 中貢獻。)

  • 當使用 tarfileshutil.unpack_archive() 解壓縮 tar 檔案時,請傳遞 filter 引數以限制可能令人意外或危險的功能。 有關詳細資訊,請參閱 提取過濾器

  • 由於 PEP 701 中引入的更改,tokenize.tokenize()tokenize.generate_tokens() 函式的輸出現在已更改。 這意味著,不再為 f 字串發出 STRING 標記,而是會生成 PEP 701 中描述的標記:除了表示式元件中標記化的相應標記外,現在還會為 f 字串的“字串”部分發出 FSTRING_STARTFSTRING_MIDDLEFSTRING_END。 例如,對於 f 字串 f"start {1+1} end",舊版本的標記器發出

    1,0-1,18:           STRING         'f"start {1+1} end"'
    

    而新版本發出

    1,0-1,2:            FSTRING_START  'f"'
    1,2-1,8:            FSTRING_MIDDLE 'start '
    1,8-1,9:            OP             '{'
    1,9-1,10:           NUMBER         '1'
    1,10-1,11:          OP             '+'
    1,11-1,12:          NUMBER         '1'
    1,12-1,13:          OP             '}'
    1,13-1,17:          FSTRING_MIDDLE ' end'
    1,17-1,18:          FSTRING_END    '"'
    

    此外,由於支援 PEP 701 所需的更改,可能還會出現一些細微的行為更改。 其中一些更改包括

    • 當標記化某些無效的 Python 字元(如 !)時,發出的標記的 type 屬性已從 ERRORTOKEN 更改為 OP

    • 不完整的單行字串現在也會像不完整的多行字串一樣引發 tokenize.TokenError

    • 某些不完整或無效的 Python 程式碼現在在標記化時會引發 tokenize.TokenError,而不是返回任意的 ERRORTOKEN 標記。

    • 不再支援在同一檔案中混合使用製表符和空格作為縮排,並且會引發 TabError

  • threading 模組現在期望 _thread 模組具有 _is_main_interpreter 屬性。 它是一個沒有引數的函式,如果當前直譯器是主直譯器,則返回 True

    任何提供自定義 _thread 模組的庫或應用程式都應提供 _is_main_interpreter()。(請參閱 gh-112826。)

構建更改

  • Python 不再使用 setup.py 來構建共享的 C 擴充套件模組。 構建引數(如標頭檔案和庫)在 configure 指令碼中檢測。 擴充套件由 Makefile 構建。 大多數擴充套件使用 pkg-config,並回退到手動檢測。(由 Christian Heimes 在 gh-93939 中貢獻。)

  • 現在需要使用兩個引數的 va_start()(如 va_start(args, format))來構建 Python。 不再使用單個引數呼叫 va_start()。(由 Kumar Aditya 在 gh-93207 中貢獻。)

  • 如果 Clang 編譯器接受該標誌,CPython 現在預設使用 ThinLTO 選項作為連結時最佳化策略。(由 Donghee Na 在 gh-89536 中貢獻。)

  • Makefile 中新增 COMPILEALL_OPTS 變數以覆蓋 compileall 選項(預設值:-j0),用於 make install。 還將 3 個 compileall 命令合併為一個命令,以一次為所有最佳化級別(0、1、2)構建 .pyc 檔案。(由 Victor Stinner 在 gh-99289 中貢獻。)

  • 為 64 位 LoongArch 新增平臺三元組

    • loongarch64-linux-gnusf

    • loongarch64-linux-gnuf32

    • loongarch64-linux-gnu

    (由 Zhang Na 在 gh-90656 中貢獻。)

  • PYTHON_FOR_REGEN 現在需要 Python 3.10 或更高版本。

  • 現在需要 Autoconf 2.71 和 aclocal 1.16.4 來重新生成 !configure。(由 Christian Heimes 在 gh-89886 中貢獻。)

  • 來自 python.org 的 Windows 構建和 macOS 安裝程式現在使用 OpenSSL 3.0。

C API 更改

新功能

  • PEP 683:引入不朽物件,允許物件繞過引用計數,以及 C-API 的相關更改

    • _Py_IMMORTAL_REFCNT:定義物件為不朽的引用計數。

      為不朽。

    • _Py_IsImmortal 檢查物件是否具有不朽的引用計數。

    • PyObject_HEAD_INIT 現在會將引用計數初始化為

      _Py_IMMORTAL_REFCNT 當與 Py_BUILD_CORE 一起使用時。

    • SSTATE_INTERNED_IMMORTAL 不朽的 interned unicode 物件的識別符號。

      是不朽的。

    • SSTATE_INTERNED_IMMORTAL_STATIC 不朽且靜態的 interned unicode 物件的識別符號

      是靜態的

    • sys.getunicodeinternedsize 這將返回已 interned 的 unicode 物件總數。

      現在需要這樣做,以便 refleak.py 正確跟蹤引用計數和已分配的塊

    (由 Eddie Elizondo 在 gh-84436 中貢獻。)

  • PEP 684:添加了新的 Py_NewInterpreterFromConfig() 函式和 PyInterpreterConfig,它們可用於建立具有自己的 GIL 的子直譯器。(有關更多資訊,請參閱 PEP 684:每個直譯器 GIL。)(由 Eric Snow 在 gh-104110 中貢獻。)

  • 在有限 C API 版本 3.12 中, Py_INCREF()Py_DECREF() 函式現在實現為不透明的函式呼叫,以隱藏實現細節。(由 Victor Stinner 在 gh-105387 中貢獻。)

移植到 Python 3.12

  • 已刪除基於 Py_UNICODE* 表示的舊版 Unicode API。請遷移到基於 UTF-8 或 wchar_t* 的 API。

  • PyArg_ParseTuple() 這樣的引數解析函式不再支援基於 Py_UNICODE* 的格式(例如 u, Z)。請遷移到其他 Unicode 格式,如 szesU

  • 所有靜態內建型別的 tp_weaklist 始終為 NULL。這是 PyTypeObject 上的一個內部欄位,但我們在此指出此更改,以防有人直接訪問該欄位。為了避免破壞,請考慮使用現有的公共 C-API,或者在必要時使用(僅限內部的)_PyObject_GET_WEAKREFS_LISTPTR() 宏。

  • 這個僅限內部的 PyTypeObject.tp_subclasses 現在可能不再是有效的物件指標。它的型別已更改為 void* 以反映這一點。我們在此說明此更改,以防有人直接訪問此僅限內部的欄位。

    要獲取子類列表,請呼叫 Python 方法 __subclasses__() (例如,使用 PyObject_CallMethod())。

  • PyUnicode_FromFormat()PyUnicode_FromFormatV() 中添加了對更多格式化選項的支援(左對齊、八進位制、大寫十六進位制、intmax_tptrdiff_twchar_t C 字串、可變寬度和精度)。(由 Serhiy Storchaka 在 gh-98836 中貢獻。)

  • PyUnicode_FromFormat()PyUnicode_FromFormatV() 中無法識別的格式字元現在會設定 SystemError。在以前的版本中,它會導致格式字串的其餘部分按原樣複製到結果字串,並丟棄任何額外的引數。(由 Serhiy Storchaka 在 gh-95781 中貢獻。)

  • 修復了 PyUnicode_FromFormat()PyUnicode_FromFormatV() 中錯誤的符號位置。(由 Philip Georgi 在 gh-95504 中貢獻。)

  • 想要新增 __dict__ 或弱引用槽的擴充套件類應分別使用 Py_TPFLAGS_MANAGED_DICTPy_TPFLAGS_MANAGED_WEAKREF,而不是 tp_dictoffsettp_weaklistoffset。仍然支援使用 tp_dictoffsettp_weaklistoffset,但它並不完全支援多重繼承 (gh-95589),並且效能可能會更差。聲明瞭 Py_TPFLAGS_MANAGED_DICT 的類必須呼叫 _PyObject_VisitManagedDict()_PyObject_ClearManagedDict() 來遍歷和清除其例項的字典。要清除弱引用,請像以前一樣呼叫 PyObject_ClearWeakRefs()

  • PyUnicode_FSDecoder() 函式不再接受類似位元組的路徑,如 bytearraymemoryview 型別:對於位元組字串,只接受精確的 bytes 型別。(由 Victor Stinner 在 gh-98393 中貢獻。)

  • Py_CLEARPy_SETREFPy_XSETREF 宏現在只計算它們的引數一次。如果引數有副作用,這些副作用將不再重複。(由 Victor Stinner 在 gh-98724 中貢獻。)

  • 直譯器的錯誤指示器現在始終被規範化。這意味著 PyErr_SetObject()PyErr_SetString() 和其他設定錯誤指示器的函式現在會在儲存異常之前將其規範化。(由 Mark Shannon 在 gh-101578 中貢獻。)

  • _Py_RefTotal 不再是權威性的,只是為了 ABI 相容性而保留。請注意,它是一個內部全域性變數,僅在除錯版本中可用。如果您碰巧正在使用它,那麼您需要開始使用 _Py_GetGlobalRefTotal()

  • 以下函式現在為新建立的型別選擇適當的元類:

    建立其元類覆蓋了 tp_new 的類已棄用,並且在 Python 3.14+ 中將被禁止。請注意,這些函式會忽略元類的 tp_new,可能會允許不完整的初始化。

    請注意,PyType_FromMetaclass()(在 Python 3.12 中新增)已經禁止建立其元類覆蓋了 tp_new 的類(Python 中的 __new__())。

    由於 tp_new 覆蓋了 PyType_From* 函式所做的幾乎所有事情,因此兩者互不相容。現有行為(在型別建立的幾個步驟中忽略元類)通常是不安全的,因為(元)類假設已呼叫 tp_new。沒有簡單的通用解決方法。以下方法之一可能對您有效:

    • 如果您控制元類,請避免在其中使用 tp_new

      • 如果可以跳過初始化,則可以在 tp_init 中完成初始化。

      • 如果不需要從 Python 例項化元類,請使用 Py_TPFLAGS_DISALLOW_INSTANTIATION 標誌將其 tp_new 設定為 NULL。這使得 PyType_From* 函式可以接受它。

    • 避免使用 PyType_From* 函式:如果您不需要 C 特有的功能(槽或設定例項大小),請透過 呼叫 元類來建立型別。

    • 如果您知道可以安全地跳過 tp_new,請使用 Python 中的 warnings.catch_warnings() 過濾掉棄用警告。

  • PyOS_InputHookPyOS_ReadlineFunctionPointer 不再在子直譯器中呼叫。這是因為客戶端通常依賴於程序範圍的全域性狀態(因為這些回撥無法恢復擴充套件模組狀態)。

    這也避免了擴充套件可能發現自己在不支援(或尚未載入)的子直譯器中執行的情況。有關更多資訊,請參閱 gh-104668

  • PyLongObject 的內部結構已更改,以獲得更好的效能。儘管 PyLongObject 的內部結構是私有的,但一些擴充套件模組會使用它們。不應再直接訪問內部欄位,而應使用以 PyLong_... 開頭的 API 函式。提供了兩個新的*不穩定*API 函式,用於高效訪問適合單個機器字的 PyLongObject 的值:

  • 現在,無論記憶體域如何,透過 PyMem_SetAllocator() 設定的自定義分配器都必須是執行緒安全的。 那些沒有自身狀態的分配器(包括“鉤子”)不受影響。 如果你的自定義分配器還不是執行緒安全的,並且需要指導,請建立一個新的 GitHub issue 並抄送 @ericsnowcurrently

已棄用

Python 3.14 中待移除

Python 3.15 中待移除

未來版本中待移除項

以下 API 已被棄用,將被移除,儘管目前尚未安排移除的日期。

已移除項

  • 移除 token.h 標頭檔案。從來沒有任何公共的詞法分析器 C API。token.h 標頭檔案僅供 Python 內部使用。(由 Victor Stinner 在 gh-92651 中貢獻。)

  • 已移除舊版的 Unicode API。 請參閱 PEP 623 瞭解詳情。

    • PyUnicode_WCHAR_KIND

    • PyUnicode_AS_UNICODE()

    • PyUnicode_AsUnicode()

    • PyUnicode_AsUnicodeAndSize()

    • PyUnicode_AS_DATA()

    • PyUnicode_FromUnicode()

    • PyUnicode_GET_SIZE()

    • PyUnicode_GetSize()

    • PyUnicode_GET_DATA_SIZE()

  • 移除 PyUnicode_InternImmortal() 函式宏。(由 Victor Stinner 在 gh-85858 中貢獻。)