Python 3.9 中的新特性

編輯:

Łukasz Langa

本文解釋了 Python 3.9 相較於 3.8 的新特性。Python 3.9 於 2020 年 10 月 5 日釋出。有關完整詳細資訊,請參閱更新日誌

參見

PEP 596 - Python 3.9 釋出時間表

摘要 – 釋出亮點

新語法功能

  • PEP 584,向 dict 添加了聯合運算子;

  • PEP 585,標準集合中的型別提示泛型;

  • PEP 614,放寬了裝飾器的語法限制。

新的內建功能

  • PEP 616,用於刪除字首和字尾的字串方法。

標準庫中的新功能

  • PEP 593,靈活的函式和變數註解;

  • 添加了os.pidfd_open(),允許在沒有競爭條件和訊號的情況下進行程序管理。

直譯器的改進

  • PEP 573,從 C 擴充套件型別方法快速訪問模組狀態;

  • PEP 617,CPython 現在使用基於 PEG 的新解析器;

  • 一些 Python 內建型別(range、tuple、set、frozenset、list、dict)現在使用PEP 590 vectorcall 加速;

  • 垃圾回收不再阻塞復活的物件;

  • 許多 Python 模組(_abcaudioop_bz2_codecs_contextvars_crypt_functools_json_localemathoperatorresourcetime_weakref)現在使用 PEP 489 定義的多階段初始化;

  • 許多標準庫模組(audioopastgrp_hashlibpwd_posixsubprocessrandomselectstructtermioszlib)現在使用 PEP 384 定義的穩定 ABI。

新庫模組

  • PEP 615,IANA 時區資料庫現在在標準庫中的 zoneinfo 模組中;

  • 新的 graphlib 模組中提供了圖的拓撲排序實現。

釋出過程變更

  • PEP 602,CPython 採用年度釋出週期。

您應該檢查程式碼中的 DeprecationWarning

當 Python 2.7 仍受支援時,Python 3 中的許多功能都保留下來,以向後相容 Python 2.7。隨著 Python 2 支援的結束,這些向後相容層已被移除或將很快移除。其中大部分已在幾年內發出了 DeprecationWarning 警告。例如,自 2012 年釋出的 Python 3.3 以來,使用 collections.Mapping 而不是 collections.abc.Mapping 就會發出 DeprecationWarning

使用 -W default 命令列選項測試您的應用程式,以檢視 DeprecationWarningPendingDeprecationWarning,甚至可以使用 -W error 將它們視為錯誤。警告過濾器可用於忽略第三方程式碼的警告。

Python 3.9 是最後一個提供這些 Python 2 向後相容層的版本,以便為 Python 專案維護者提供更多時間來組織移除 Python 2 支援並新增對 Python 3.9 的支援。

collections 模組中 抽象基類 的別名,例如 collections.Mapping 別名到 collections.abc.Mapping,為了向後相容性,將保留到最後一個版本。它們將在 Python 3.10 中移除。

更一般地,嘗試在Python 開發模式中執行測試,這有助於準備程式碼以使其與下一個 Python 版本相容。

注意:此版本的 Python 中也移除了一些已有的棄用。請參閱移除部分。

新功能

字典合併與更新運算子

合併 (|) 和更新 (|=) 運算子已新增到內建的 dict 類中。它們補充了現有的 dict.update{**d1, **d2} 合併字典的方法。

示例

>>> x = {"key1": "value1 from x", "key2": "value2 from x"}
>>> y = {"key2": "value2 from y", "key3": "value3 from y"}
>>> x | y
{'key1': 'value1 from x', 'key2': 'value2 from y', 'key3': 'value3 from y'}
>>> y | x
{'key2': 'value2 from x', 'key3': 'value3 from y', 'key1': 'value1 from x'}

有關完整說明,請參閱PEP 584。(由 Brandt Bucher 在bpo-36144中貢獻。)

新的字串方法,用於刪除字首和字尾

已新增 str.removeprefix(prefix)str.removesuffix(suffix),以便輕鬆從字串中刪除不需要的字首或字尾。相應的 bytesbytearraycollections.UserString 方法也已新增。有關完整說明,請參閱PEP 616。(由 Dennis Sweeney 在bpo-39939中貢獻。)

標準集合中的型別提示泛型

在型別註解中,您現在可以使用內建的集合型別,例如 listdict 作為泛型型別,而不是從 typing 中匯入相應的首字母大寫的型別(例如 ListDict)。標準庫中的其他一些型別現在也是泛型的,例如 queue.Queue

示例

def greet_all(names: list[str]) -> None:
    for name in names:
        print("Hello", name)

有關更多詳細資訊,請參閱PEP 585。(由 Guido van Rossum、Ethan Smith 和 Batuhan Taşkaya 在bpo-39481中貢獻。)

新解析器

Python 3.9 使用一個新的解析器,基於 PEG 而不是 LL(1)。新解析器的效能大致與舊解析器相當,但在設計新語言功能時,PEG 形式比 LL(1) 更靈活。我們將在 Python 3.10 及更高版本中開始利用這種靈活性。

ast 模組使用新解析器並生成與舊解析器相同的 AST。

在 Python 3.10 中,舊解析器將被刪除,所有依賴於它的功能(主要是 parser 模組,該模組早已棄用)也將被刪除。僅在 Python 3.9 中,您可以使用命令列開關 (-X oldparser) 或環境變數 (PYTHONOLDPARSER=1) 切換回 LL(1) 解析器。

有關更多詳細資訊,請參閱PEP 617。(由 Guido van Rossum、Pablo Galindo 和 Lysandros Nikolaou 在bpo-40334中貢獻。)

其他語言更改

  • __import__() 現在引發 ImportError,而不是 ValueError,以前當相對匯入超出其頂級包時會發生這種情況。(由 Ngalim Siregar 在bpo-37444中貢獻。)

  • Python 現在獲取命令列上指定的指令碼檔名的絕對路徑(例如:python3 script.py):__main__ 模組的 __file__ 屬性變為絕對路徑,而不是相對路徑。在透過 os.chdir() 更改當前目錄後,這些路徑仍然有效。作為副作用,在這種情況下,回溯還顯示 __main__ 模組幀的絕對路徑。(由 Victor Stinner 在bpo-20443中貢獻。)

  • Python 開發模式除錯構建中,現在會檢查字串編碼和解碼操作的 encodingerrors 引數。例如:open()str.encode()bytes.decode()

    預設情況下,為了獲得最佳效能,僅在第一次編碼/解碼錯誤時檢查 errors 引數,並且有時會忽略空字串的 encoding 引數。(由 Victor Stinner 在bpo-37388中貢獻。)

  • "".replace("", s, n) 現在對於所有非零 n 返回 s 而不是空字串。它現在與 "".replace("", s) 一致。bytesbytearray 物件也有類似的更改。(由 Serhiy Storchaka 在bpo-28029中貢獻。)

  • 任何有效的表示式現在都可以用作裝飾器。以前,語法更加嚴格。有關詳細資訊,請參閱PEP 614。(由 Brandt Bucher 在bpo-39702中貢獻。)

  • 改進了 typing 模組的幫助。現在為所有特殊形式和特殊泛型別名(如 UnionList)顯示 docstring。將 help() 與泛型別名(如 List[int])一起使用將顯示相應具體型別(本例中為 list)的幫助。(由 Serhiy Storchaka 在bpo-40257中貢獻。)

  • 現在禁止並行執行 aclose() / asend() / athrow(),並且 ag_running 現在反映非同步生成器的實際執行狀態。(由 Yury Selivanov 在bpo-30773中貢獻。)

  • in 運算子和 operator 模組的函式 contains()indexOf()countOf() 中,呼叫 __iter__ 方法時出現的意外錯誤不再被 TypeError 掩蓋。(由 Serhiy Storchaka 在bpo-40824中貢獻。)

  • 未加括號的 lambda 表示式不能再用作列表推導式和生成器表示式中 if 子句的表示式部分。有關詳細資訊,請參閱 bpo-41848bpo-43755

新模組

zoneinfo

zoneinfo 模組為標準庫帶來了對 IANA 時區資料庫的支援。它添加了 zoneinfo.ZoneInfo,這是一個由系統時區資料支援的具體 datetime.tzinfo 實現。

示例

>>> from zoneinfo import ZoneInfo
>>> from datetime import datetime, timedelta

>>> # Daylight saving time
>>> dt = datetime(2020, 10, 31, 12, tzinfo=ZoneInfo("America/Los_Angeles"))
>>> print(dt)
2020-10-31 12:00:00-07:00
>>> dt.tzname()
'PDT'

>>> # Standard time
>>> dt += timedelta(days=7)
>>> print(dt)
2020-11-07 12:00:00-08:00
>>> print(dt.tzname())
PST

作為未提供 IANA 資料庫的平臺的資料回退源,tzdata 模組作為第一方包釋出——透過 PyPI 分發並由 CPython 核心團隊維護。

參見

PEP 615 – 標準庫中對 IANA 時區資料庫的支援

由 Paul Ganssle 撰寫並實現的 PEP

graphlib

添加了一個新模組 graphlib,其中包含 graphlib.TopologicalSorter 類,提供圖的拓撲排序功能。(由 Pablo Galindo、Tim Peters 和 Larry Hastings 在bpo-17005中貢獻。)

改進的模組

ast

dump() 添加了 indent 選項,允許其生成多行縮排輸出。(由 Serhiy Storchaka 在bpo-37995中貢獻。)

ast 模組中添加了 ast.unparse() 函式,該函式可用於解析 ast.AST 物件並生成一個字串程式碼,該程式碼在解析時將生成等效的 ast.AST 物件。(由 Pablo Galindo 和 Batuhan Taskaya 在bpo-38870中貢獻。)

為 AST 節點添加了 docstring,其中包含用於構建該節點的 ASDL 簽名。(由 Batuhan Taskaya 在bpo-39638中貢獻。)

asyncio

由於重大的安全問題,不再支援 asyncio.loop.create_datagram_endpoint()reuse_address 引數。這是由於 SO_REUSEADDR 套接字選項在 UDP 中的行為。有關更多詳細資訊,請參見 loop.create_datagram_endpoint() 的文件。(由 Kyle Stanley、Antoine Pitrou 和 Yury Selivanov 在 bpo-37228 中貢獻。)

添加了一個新的協程 shutdown_default_executor(),它安排預設執行器的關閉,等待 ThreadPoolExecutor 完成關閉。此外,asyncio.run() 已更新以使用新的協程。(由 Kyle Stanley 在bpo-34037中貢獻。)

增加了 asyncio.PidfdChildWatcher,一個特定於 Linux 的子程序監視器實現,它輪詢程序檔案描述符。(bpo-38692

添加了一個新的協程 asyncio.to_thread()。它主要用於在單獨的執行緒中執行 I/O 密集型函式,以避免阻塞事件迴圈,並且本質上是 run_in_executor() 的高階版本,可以直接接受關鍵字引數。(由 Kyle Stanley 和 Yury Selivanov 在bpo-32309中貢獻。)

由於超時而取消任務時,asyncio.wait_for() 現在將等待取消完成,即使 timeout 小於等於 0,就像它處理正超時一樣。(由 Elvis Pranskevichus 在bpo-32751中貢獻。)

asyncio 現在在呼叫與 ssl.SSLSocket 套接字不相容的方法時引發 TypeError。(由 Ido Michael 在bpo-37404中貢獻。)

compileall

增加了對重複 .pyc 檔案使用硬連結的新可能性:hardlink_dupes 引數和 –hardlink-dupes 命令列選項。(由 Lumír ‘Frenzy’ Balhar 在bpo-40495中貢獻。)

添加了用於在生成的 .pyc 檔案中進行路徑操作的新選項:stripdirprependdirlimit_sl_dest 引數以及 -s、-p、-e 命令列選項。添加了多次指定最佳化級別選項的可能性。(由 Lumír ‘Frenzy’ Balhar 在bpo-38112中貢獻。)

concurrent.futures

concurrent.futures.Executor.shutdown() 添加了一個新的 cancel_futures 引數,該引數取消所有尚未開始執行的待處理 future,而不是等待它們完成才關閉執行器。(由 Kyle Stanley 在bpo-39349中貢獻。)

ThreadPoolExecutorProcessPoolExecutor 中移除了守護執行緒。這改善了與子直譯器的相容性以及其關閉過程的可預測性。(由 Kyle Stanley 在bpo-39812中貢獻。)

ProcessPoolExecutor 中的工作程序現在按需生成,僅當沒有可用的空閒工作程序可重用時。這優化了啟動開銷並減少了因空閒工作程序而損失的 CPU 時間。(由 Kyle Stanley 在bpo-39207中貢獻。)

curses

添加了 curses.get_escdelay()curses.set_escdelay()curses.get_tabsize()curses.set_tabsize() 函式。(由 Anthony Sottile 在bpo-38312中貢獻。)

datetime

datetime.dateisocalendar() 方法和 datetime.datetimeisocalendar() 方法現在返回 namedtuple() 而不是 tuple。(由 Donghee Na 在bpo-24416中貢獻。)

distutils

upload 命令現在建立 SHA2-256 和 Blake2b-256 雜湊摘要。它在阻止 MD5 摘要的平臺上跳過 MD5。(由 Christian Heimes 在bpo-40698中貢獻。)

fcntl

添加了常量 fcntl.F_OFD_GETLKfcntl.F_OFD_SETLKfcntl.F_OFD_SETLKW。(由 Donghee Na 在bpo-38602中貢獻。)

ftplib

FTPFTP_TLS 現在,如果其建構函式給定的超時為零,則會引發 ValueError,以防止建立非阻塞套接字。(由 Donghee Na 在bpo-39259中貢獻。)

gc

當垃圾回收器進行回收時,如果一些物件復活(在終結器執行後,它們可以從隔離的迴圈外部訪問),則不會阻止所有仍然無法訪問的物件的回收。(由 Pablo Galindo 和 Tim Peters 在bpo-38379中貢獻。)

添加了一個新函式 gc.is_finalized() 來檢查物件是否已被垃圾回收器終結。(由 Pablo Galindo 在bpo-39322中貢獻。)

hashlib

hashlib 模組現在可以在可用時使用 OpenSSL 的 SHA3 雜湊和 SHAKE XOF。(由 Christian Heimes 在bpo-37630中貢獻。)

內建雜湊模組現在可以透過 ./configure --without-builtin-hashlib-hashes 停用,或者透過例如 ./configure --with-builtin-hashlib-hashes=sha3,blake2 有選擇地啟用,以強制使用基於 OpenSSL 的實現。(由 Christian Heimes 在bpo-40479中貢獻)

http

HTTP 狀態碼 103 EARLY_HINTS418 IM_A_TEAPOT425 TOO_EARLY 已新增到 http.HTTPStatus。(由 Donghee Na 在bpo-39509和 Ross Rhodes 在bpo-39507中貢獻。)

IDLE 和 idlelib

添加了關閉游標閃爍的選項。(由 Zackery Spytz 在bpo-4603中貢獻。)

Escape 鍵現在關閉 IDLE 補全視窗。(由 Johnny Najera 在bpo-38944中貢獻。)

添加了關鍵字到模組名補全列表。(由 Terry J. Reedy 在bpo-37765中貢獻。)

3.9 維護版本中的新功能

使 IDLE 呼叫 sys.excepthook()(在不帶“-n”啟動時)。以前使用者鉤子會被忽略。(由 Ken Hilton 在bpo-43008中貢獻。)

上述更改已反向移植到 3.8 維護版本。

重新排列設定對話方塊。將“常規”選項卡拆分為“視窗”和“Shell/Ed”選項卡。將擴充套件“幫助”選單的幫助源移動到“擴充套件”選項卡。為新選項騰出空間並縮短對話方塊。後者使對話方塊更好地適應小螢幕。(由 Terry Jan Reedy 在bpo-40468中貢獻。)將縮排空間設定從“字型”選項卡移動到新的“視窗”選項卡。(由 Mark Roseman 和 Terry Jan Reedy 在bpo-33962中貢獻。)

.pyi 檔案應用語法高亮。(由 Alex Waygood 和 Terry Jan Reedy 在 bpo-45447 中貢獻。)

imaplib

IMAP4IMAP4_SSL 的建構函式現在具有一個可選的 timeout 引數。此外,open() 方法現在也具有一個可選的 timeout 引數。此更改已應用於 IMAP4_SSLIMAP4_stream 的重寫方法。(由 Donghee Na 在bpo-38615中貢獻。)

添加了 imaplib.IMAP4.unselect()imaplib.IMAP4.unselect() 釋放與所選郵箱關聯的伺服器資源,並將伺服器返回到已認證狀態。此命令執行與 imaplib.IMAP4.close() 相同的操作,但不會從當前選定郵箱中永久移除任何訊息。(由 Donghee Na 在bpo-40375中貢獻。)

importlib

為了提高與 import 語句的一致性,importlib.util.resolve_name() 現在對於無效的相對匯入嘗試會引發 ImportError 而不是 ValueError。(由 Ngalim Siregar 在bpo-37444中貢獻。)

釋出不可變模組物件的匯入載入器現在除了單個模組外,還可以釋出不可變包。(由 Dino Viehland 在bpo-39336中貢獻。)

添加了 importlib.resources.files() 函式,支援包資料中的子目錄,與 importlib_resources 1.5 版本中的反向移植匹配。(由 Jason R. Coombs 在bpo-39791中貢獻。)

importlib_metadata 1.6.1 版本重新整理了 importlib.metadata

inspect

inspect.BoundArguments.argumentsOrderedDict 更改為普通 dict。(由 Inada Naoki 在bpo-36350bpo-39775中貢獻。)

ipaddress

ipaddress 現在支援 IPv6 範圍地址(帶有後綴 %<scope_id> 的 IPv6 地址)。

可以使用 ipaddress.IPv6Address 解析範圍 IPv6 地址。如果存在,可以透過 scope_id 屬性獲取範圍區域 ID。(由 Oleksandr Pavliuk 在bpo-34788中貢獻。)

從 Python 3.9.5 開始,ipaddress 模組不再接受 IPv4 地址字串中的任何前導零。(由 Christian Heimes 在bpo-36384中貢獻)。

math

擴充套件了 math.gcd() 函式以處理多個引數。以前,它只支援兩個引數。(由 Serhiy Storchaka 在bpo-39648中貢獻。)

添加了 math.lcm():返回指定引數的最小公倍數。(由 Mark Dickinson、Ananthakrishnan 和 Serhiy Storchaka 在bpo-39479bpo-39648中貢獻。)

添加了 math.nextafter():返回 x 之後朝向 y 的下一個浮點值。(由 Victor Stinner 在bpo-39288中貢獻。)

添加了 math.ulp():返回浮點數最低有效位的值。(由 Victor Stinner 在bpo-39310中貢獻。)

multiprocessing

multiprocessing.SimpleQueue 類有一個新的 close() 方法,用於顯式關閉佇列。(由 Victor Stinner 在bpo-30966中貢獻。)

nntplib

NNTPNNTP_SSL 現在,如果其建構函式給定的超時為零,則會引發 ValueError,以防止建立非阻塞套接字。(由 Donghee Na 在bpo-39259中貢獻。)

os

si_code 添加了 CLD_KILLEDCLD_STOPPED。(由 Donghee Na 在bpo-38493中貢獻。)

公開了特定於 Linux 的 os.pidfd_open() (bpo-38692) 和 os.P_PIDFD (bpo-38713),用於透過檔案描述符進行程序管理。

os.unsetenv() 函式現在在 Windows 上也可用。(由 Victor Stinner 在bpo-39413中貢獻。)

os.putenv()os.unsetenv() 函式現在始終可用。(由 Victor Stinner 在bpo-39395中貢獻。)

添加了 os.waitstatus_to_exitcode() 函式:將等待狀態轉換為退出程式碼。(由 Victor Stinner 在bpo-40094中貢獻。)

pathlib

添加了 pathlib.Path.readlink(),其行為類似於 os.readlink()。(由 Girts Folkmanis 在bpo-30618中貢獻)

pdb

在 Windows 上,Pdb 現在支援 ~/.pdbrc。(由 Tim Hopper 和 Dan Lidral-Porter 在bpo-20523中貢獻。)

poplib

POP3POP3_SSL 現在,如果其建構函式給定的超時為零,則會引發 ValueError,以防止建立非阻塞套接字。(由 Donghee Na 在bpo-39259中貢獻。)

pprint

pprint 現在可以美觀地列印 types.SimpleNamespace。(由 Carl Bordum Hansen 在bpo-37376中貢獻。)

pydoc

現在,文件字串不僅顯示類、函式、方法等,還顯示任何具有自己的 __doc__ 屬性的物件。(由 Serhiy Storchaka 在bpo-40257中貢獻。)

random

添加了一個新的 random.Random.randbytes() 方法:生成隨機位元組。(由 Victor Stinner 在bpo-40286中貢獻。)

訊號

公開了特定於 Linux 的 signal.pidfd_send_signal(),用於使用檔案描述符而不是 pid 向程序傳送訊號。(bpo-38712

smtplib

SMTPSMTP_SSL 現在,如果其建構函式給定的超時為零,則會引發 ValueError,以防止建立非阻塞套接字。(由 Donghee Na 在bpo-39259中貢獻。)

LMTP 建構函式現在有一個可選的 timeout 引數。(由 Donghee Na 在bpo-39329中貢獻。)

socket

socket 模組現在在 Linux 4.1 及更高版本上匯出 CAN_RAW_JOIN_FILTERS 常量。(由 Stefan Tatschner 和 Zackery Spytz 在bpo-25780中貢獻。)

socket 模組現在支援 CAN_J1939 協議,只要平臺支援它。(由 Karl Ding 在bpo-40291中貢獻。)

socket 模組現在有 socket.send_fds()socket.recv_fds() 函式。(由 Joannah Nanjekye、Shinya Okano 和 Victor Stinner 在bpo-28724中貢獻。)

時間

在 AIX 上,thread_time() 現在使用具有納秒解析度的 thread_cputime() 實現,而不是具有 10 毫秒解析度的 clock_gettime(CLOCK_THREAD_CPUTIME_ID)。(由 Batuhan Taskaya 在bpo-40192中貢獻)

sys

添加了一個新的 sys.platlibdir 屬性:平臺特定庫目錄的名稱。它用於構建標準庫的路徑和已安裝擴充套件模組的路徑。在大多數平臺上,它等於 "lib"。在 Fedora 和 SuSE 上,在 64 位平臺上,它等於 "lib64"。(由 Jan Matějek、Matěj Cepl、Charalampos Stratakis 和 Victor Stinner 在bpo-1294959中貢獻。)

以前,非互動式時,sys.stderr 是塊緩衝的。現在 stderr 預設為始終行緩衝。(由 Jendrik Seipp 在bpo-13601中貢獻。)

tracemalloc

添加了 tracemalloc.reset_peak(),用於將跟蹤記憶體塊的峰值大小設定為當前大小,以測量特定程式碼段的峰值。(由 Huon Wilson 在bpo-40630中貢獻。)

typing

PEP 593 引入了 typing.Annotated 型別,用於使用上下文特定元資料裝飾現有型別,並向 typing.get_type_hints() 添加了新的 include_extras 引數,以在執行時訪問元資料。(由 Till Varoquaux 和 Konstantin Kashin 貢獻。)

unicodedata

Unicode 資料庫已更新到版本 13.0.0。(bpo-39926)。

venv

venv 提供的啟用指令碼現在都透過始終使用 __VENV_PROMPT__ 指定的值來一致地定製其提示。以前,一些指令碼無條件使用 __VENV_PROMPT__,另一些僅在恰好設定時使用(這是預設情況),一個則使用 __VENV_NAME__。 (由 Brett Cannon 在bpo-37663中貢獻。)

xml

xml.etree.ElementTree 序列化為 XML 檔案時,屬性中的空格字元現在會保留。換行符不再標準化為“n”。這是關於如何解釋 XML 規範第 2.11 節的討論結果。(由 Mefistotelis 在bpo-39011中貢獻。)

最佳化

  • 優化了列表推導式中臨時變數賦值的慣用語法。現在,列表推導式中的 for y in [expr] 與簡單的賦值 y = expr 一樣快。例如

    sums = [s for s in [0] for x in data for s in [s + x]]

    := 運算子不同,這種慣用語法不會將變數洩露到外部作用域。

    (由 Serhiy Storchaka 在bpo-32856中貢獻。)

  • 優化了多執行緒應用程式中的訊號處理。如果主執行緒以外的執行緒接收到訊號,則位元組碼求值迴圈不再在每個位元組碼指令處中斷以檢查無法處理的待處理訊號。只有主直譯器的主執行緒才能處理訊號。

    以前,位元組碼求值迴圈會在每個指令處中斷,直到主執行緒處理訊號。(由 Victor Stinner 在bpo-40010中貢獻。)

  • 優化了在 FreeBSD 上使用 closefrom()subprocess 模組。(由 Ed Maste、Conrad Meyer、Kyle Evans、Kubilay Kocak 和 Victor Stinner 在bpo-38061中貢獻。)

  • PyLong_FromDouble() 對於適合 long 的值現在速度提高了 1.87 倍。(由 Sergey Fedoseev 在bpo-37986中貢獻。)

  • 許多 Python 內建函式(rangetuplesetfrozensetlistdict)現在透過使用 PEP 590 vectorcall 協議加速。(由 Donghee Na、Mark Shannon、Jeroen Demeyer 和 Petr Viktorin 在bpo-37207中貢獻。)

  • 當其他集合遠大於基礎集合時,優化了 set.difference_update()。(由 Evgeny Kapun 建議,Michele Orrù 在bpo-8425中貢獻程式碼。)

  • Python 的小物件分配器(obmalloc.c)現在允許(不多於)一個空競技場保持可用以立即重用,而無需將其返回給作業系統。這可以防止在簡單迴圈中出現抖動,因為在每次迭代中都會建立和銷燬一個新的競技場。(由 Tim Peters 在bpo-37257中貢獻。)

  • 浮點數的向下取整除法操作現在具有更好的效能。此外,此操作的 ZeroDivisionError 訊息也已更新。(由 Donghee Na 在bpo-39434中貢獻。)

  • 使用 UTF-8 和 ascii 編碼解碼短 ASCII 字串現在快了大約 15%。(由 Inada Naoki 在bpo-37348中貢獻。)

以下是 Python 3.4 到 Python 3.9 的效能改進總結

Python version                       3.4     3.5     3.6     3.7     3.8    3.9
--------------                       ---     ---     ---     ---     ---    ---

Variable and attribute read access:
    read_local                       7.1     7.1     5.4     5.1     3.9    3.9
    read_nonlocal                    7.1     8.1     5.8     5.4     4.4    4.5
    read_global                     15.5    19.0    14.3    13.6     7.6    7.8
    read_builtin                    21.1    21.6    18.5    19.0     7.5    7.8
    read_classvar_from_class        25.6    26.5    20.7    19.5    18.4   17.9
    read_classvar_from_instance     22.8    23.5    18.8    17.1    16.4   16.9
    read_instancevar                32.4    33.1    28.0    26.3    25.4   25.3
    read_instancevar_slots          27.8    31.3    20.8    20.8    20.2   20.5
    read_namedtuple                 73.8    57.5    45.0    46.8    18.4   18.7
    read_boundmethod                37.6    37.9    29.6    26.9    27.7   41.1

Variable and attribute write access:
    write_local                      8.7     9.3     5.5     5.3     4.3    4.3
    write_nonlocal                  10.5    11.1     5.6     5.5     4.7    4.8
    write_global                    19.7    21.2    18.0    18.0    15.8   16.7
    write_classvar                  92.9    96.0   104.6   102.1    39.2   39.8
    write_instancevar               44.6    45.8    40.0    38.9    35.5   37.4
    write_instancevar_slots         35.6    36.1    27.3    26.6    25.7   25.8

Data structure read access:
    read_list                       24.2    24.5    20.8    20.8    19.0   19.5
    read_deque                      24.7    25.5    20.2    20.6    19.8   20.2
    read_dict                       24.3    25.7    22.3    23.0    21.0   22.4
    read_strdict                    22.6    24.3    19.5    21.2    18.9   21.5

Data structure write access:
    write_list                      27.1    28.5    22.5    21.6    20.0   20.0
    write_deque                     28.7    30.1    22.7    21.8    23.5   21.7
    write_dict                      31.4    33.3    29.3    29.2    24.7   25.4
    write_strdict                   28.4    29.9    27.5    25.2    23.1   24.5

Stack (or queue) operations:
    list_append_pop                 93.4   112.7    75.4    74.2    50.8   50.6
    deque_append_pop                43.5    57.0    49.4    49.2    42.5   44.2
    deque_append_popleft            43.7    57.3    49.7    49.7    42.8   46.4

Timing loop:
    loop_overhead                    0.5     0.6     0.4     0.3     0.3    0.3

這些結果是從以下可變訪問基準指令碼生成的:Tools/scripts/var_access_benchmark.py。該基準指令碼以納秒顯示時間。基準測試是在執行 python.org 上 macOS 64 位構建的 Intel® Core™ i7-4960HQ 處理器上測量的。

已棄用

  • distutils bdist_msi 命令現在已棄用,請改用 bdist_wheel(wheel 包)。(由 Hugo van Kemenade 在bpo-39586中貢獻。)

  • 目前 math.factorial() 接受具有非負整數值的 float 例項(例如 5.0)。對於非整數和負浮點數,它會引發 ValueError。此功能現已棄用。在未來的 Python 版本中,它將對所有浮點數引發 TypeError。(由 Serhiy Storchaka 在 bpo-37315 中貢獻。)

  • parsersymbol 模組已棄用,並將在未來版本的 Python 中移除。對於大多數用例,使用者可以使用 ast 模組,利用抽象語法樹 (AST) 生成和編譯階段。

  • 公共 C API 函式 PyParser_SimpleParseStringFlags()PyParser_SimpleParseStringFlagsFilename()PyParser_SimpleParseFileFlags()PyNode_Compile() 已棄用,並將在 Python 3.10 中與舊解析器一起移除。

  • 在布林上下文中使用 NotImplemented 已棄用,因為它幾乎都是不正確的富比較器實現的結果。在未來的 Python 版本中,它將變為 TypeError。(由 Josh Rosenberg 在 bpo-35712 中貢獻。)

  • random 模組目前接受任何可雜湊型別作為可能的種子值。不幸的是,其中一些型別不保證具有確定性的雜湊值。Python 3.9 之後,該模組將限制其種子為 Noneintfloatstrbytesbytearray

  • 在未指定 mode 引數的情況下開啟 GzipFile 檔案進行寫入已棄用。在未來的 Python 版本中,它將預設始終以讀取模式開啟。請指定 mode 引數以寫入方式開啟並消除警告。(由 Serhiy Storchaka 在 bpo-28286 中貢獻。)

  • _tkinter.TkappTypesplit() 方法已棄用,轉而使用行為更一致和可預測的 splitlist() 方法。(由 Serhiy Storchaka 在 bpo-38371 中貢獻。)

  • 將協程物件顯式傳遞給 asyncio.wait() 已棄用,並將在 3.11 版本中移除。(由 Yury Selivanov 和 Kyle Stanley 在 bpo-34790 中貢獻。)

  • binhex4 和 hexbin4 標準現已棄用。 binhex 模組和以下 binascii 函式現已棄用

    • b2a_hqx(), a2b_hqx()

    • rlecode_hqx(), rledecode_hqx()

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

  • astsliceIndexExtSlice 被視為已棄用,並將在未來的 Python 版本中移除。value 本身應替代 Index(value)Tuple(slices, Load()) 應替代 ExtSlice(slices)。(由 Serhiy Storchaka 在 bpo-34822 中貢獻。)

  • astSuiteParamAugLoadAugStore 被視為已棄用,並將在未來的 Python 版本中移除。它們在 Python 3 中未由解析器生成,也未被程式碼生成器接受。(由 Batuhan Taskaya 在 bpo-39639bpo-39969 中貢獻,由 Serhiy Storchaka 在 bpo-39988 中貢獻。)

  • PyEval_InitThreads()PyEval_ThreadsInitialized() 函式現已棄用,並將在 Python 3.11 中移除。現在呼叫 PyEval_InitThreads() 不執行任何操作。GIL 自 Python 3.7 起由 Py_Initialize() 初始化。(由 Victor Stinner 在 bpo-39877 中貢獻。)

  • None 作為第一個引數傳遞給 shlex.split() 函式已棄用。(由 Zackery Spytz 在 bpo-33262 中貢獻。)

  • smtpd.MailmanProxy() 現已棄用,因為它在沒有外部模組 mailman 的情況下無法使用。(由 Samuel Colvin 在 bpo-35800 中貢獻。)

  • lib2to3 模組現在發出 PendingDeprecationWarning。Python 3.9 切換到 PEG 解析器(參見 PEP 617),Python 3.10 可能包含 lib2to3 的 LL(1) 解析器無法解析的新語言語法。 lib2to3 模組可能會在未來的 Python 版本中從標準庫中移除。考慮第三方替代方案,例如 LibCSTparso。(由 Carl Meyer 在 bpo-40360 中貢獻。)

  • random.shuffle()random 引數已棄用。(由 Raymond Hettinger 在 bpo-40465 中貢獻)

已移除

  • unittest.mock.__version__ 中的錯誤版本已移除。

  • nntplib.NNTP: xpath()xgtitle() 方法已移除。這些方法自 Python 3.3 起已棄用。通常,NNTP 伺服器管理員不支援或不啟用這些擴充套件。對於 xgtitle(),請改用 nntplib.NNTP.descriptions()nntplib.NNTP.description()。(由 Donghee Na 在 bpo-39366 中貢獻。)

  • array.array: tostring()fromstring() 方法已移除。它們是 tobytes()frombytes() 的別名,自 Python 3.2 起已棄用。(由 Victor Stinner 在 bpo-38916 中貢獻。)

  • 未文件化的 sys.callstats() 函式已移除。自 Python 3.7 起,它已棄用並始終返回 None。它需要一個特殊構建選項 CALL_PROFILE,該選項在 Python 3.7 中已移除。(由 Victor Stinner 在 bpo-37414 中貢獻。)

  • sys.getcheckinterval()sys.setcheckinterval() 函式已移除。它們自 Python 3.2 起已棄用。請改用 sys.getswitchinterval()sys.setswitchinterval()。(由 Victor Stinner 在 bpo-37392 中貢獻。)

  • C 函式 PyImport_Cleanup() 已移除。它被記錄為:“清空模組表。僅供內部使用。”(由 Victor Stinner 在 bpo-36710 中貢獻。)

  • _dummy_threaddummy_threading 模組已移除。這些模組自 Python 3.7 起已棄用,因為它需要執行緒支援。(由 Victor Stinner 在 bpo-37312 中貢獻。)

  • aifc.openfp()aifc.open() 的別名)、sunau.openfp()sunau.open() 的別名)和 wave.openfp()wave.open() 的別名)已移除。它們自 Python 3.7 起已棄用。(由 Victor Stinner 在 bpo-37320 中貢獻。)

  • threading.ThreadisAlive() 方法已移除。它自 Python 3.8 起已棄用。請改用 is_alive()。(由 Donghee Na 在 bpo-37804 中貢獻。)

  • ElementTree 模組中 ElementTreeElement 類的 getchildren()getiterator() 方法已移除。它們在 Python 3.2 中已棄用。請使用 iter(x)list(x) 代替 x.getchildren(),並使用 x.iter()list(x.iter()) 代替 x.getiterator()。(由 Serhiy Storchaka 在 bpo-36543 中貢獻。)

  • 舊的 plistlib API 已移除,它自 Python 3.4 起已棄用。請使用 load()loads()dump()dumps() 函式。此外, use_builtin_types 引數已移除,始終使用標準 bytes 物件代替。(由 Jon Janzen 在 bpo-36409 中貢獻。)

  • C 函式 PyGen_NeedsFinalizing 已移除。在實現 PEP 442 後,它在 CPython 中未被文件化、測試或使用。由 Joannah Nanjekye 提交補丁。(由 Joannah Nanjekye 在 bpo-15088 中貢獻)

  • base64.encodestring()base64.decodestring()(自 Python 3.1 起棄用的別名)已移除:請改用 base64.encodebytes()base64.decodebytes()。(由 Victor Stinner 在 bpo-39351 中貢獻。)

  • fractions.gcd() 函式已移除,它自 Python 3.5 起已棄用(bpo-22486):請改用 math.gcd()。(由 Victor Stinner 在 bpo-39350 中貢獻。)

  • bz2.BZ2Filebuffering 引數已移除。自 Python 3.0 起,它被忽略,並且使用它會發出 DeprecationWarning。請傳遞一個已開啟的檔案物件來控制檔案的開啟方式。(由 Victor Stinner 在 bpo-39357 中貢獻。)

  • json.loads()encoding 引數已移除。自 Python 3.1 起,它已棄用並被忽略;自 Python 3.8 起,使用它會發出 DeprecationWarning。(由 Inada Naoki 在 bpo-39377 中貢獻)

  • with (await asyncio.lock):with (yield from asyncio.lock): 語句不再受支援,請改用 async with lockasyncio.Conditionasyncio.Semaphore 也是如此。(由 Andrew Svetlov 在 bpo-34793 中貢獻。)

  • sys.getcounts() 函式、 -X showalloccount 命令列選項以及 C 結構 PyConfigshow_alloc_count 欄位已移除。它們需要透過定義 COUNT_ALLOCS 宏的特殊 Python 構建。(由 Victor Stinner 在 bpo-39489 中貢獻。)

  • typing.NamedTuple 類的 _field_types 屬性已移除。它自 Python 3.8 起已棄用。請改用 __annotations__ 屬性。(由 Serhiy Storchaka 在 bpo-40182 中貢獻。)

  • symtable.SymbolTable.has_exec() 方法已移除。它自 2006 年起已棄用,並且在呼叫時僅返回 False。(由 Batuhan Taskaya 在 bpo-40208 中貢獻)

  • asyncio.Task.current_task()asyncio.Task.all_tasks() 已移除。它們自 Python 3.7 起已棄用,您可以使用 asyncio.current_task()asyncio.all_tasks() 代替。(由 Rémi Lapeyre 在 bpo-40967 中貢獻)

  • html.parser.HTMLParser 類中的 unescape() 方法已移除(它自 Python 3.4 起已棄用)。應使用 html.unescape() 將字元引用轉換為相應的 Unicode 字元。

移植到 Python 3.9

本節列出了前面描述過的變更以及其他可能需要修改程式碼的 bug 修復。

Python API 的變化

  • __import__()importlib.util.resolve_name() 現在在以前引發 ValueError 的地方引發 ImportError。呼叫方捕獲特定異常型別並支援 Python 3.9 及更早版本時,需要使用 except (ImportError, ValueError): 同時捕獲兩者。

  • __VENV_PROMPT__ 設定為 "" 時, venv 啟用指令碼不再進行特殊處理。

  • select.epoll.unregister() 方法不再忽略 EBADF 錯誤。(由 Victor Stinner 在 bpo-39239 中貢獻。)

  • bz2.BZ2Filecompresslevel 引數變為僅關鍵字引數,因為 buffering 引數已移除。(由 Victor Stinner 在 bpo-39357 中貢獻。)

  • 簡化的 AST 用於訂閱。簡單索引將由其值表示,擴充套件切片將表示為元組。Index(value) 將返回 value 本身,ExtSlice(slices) 將返回 Tuple(slices, Load())。(由 Serhiy Storchaka 在 bpo-34822 中貢獻。)

  • 當使用 -E-I 命令列選項時, importlib 模組現在會忽略 PYTHONCASEOK 環境變數。

  • encoding 引數已作為僅關鍵字引數新增到 ftplib.FTPftplib.FTP_TLS 類中,並且預設編碼已從 Latin-1 更改為 UTF-8,以遵循 RFC 2640

  • asyncio.loop.shutdown_default_executor() 已新增到 AbstractEventLoop,這意味著繼承自它的替代事件迴圈應該定義此方法。(由 Kyle Stanley 在 bpo-34037 中貢獻。)

  • __future__ 模組中未來標誌的常量值已更新,以防止與編譯器標誌衝突。以前 PyCF_ALLOW_TOP_LEVEL_AWAITCO_FUTURE_DIVISION 衝突。(由 Batuhan Taskaya 在 bpo-39562 中貢獻)

  • array('u') 現在使用 wchar_t 作為 C 型別,而不是 Py_UNICODE。此更改不影響其行為,因為 Py_UNICODE 自 Python 3.3 起就是 wchar_t 的別名。(由 Inada Naoki 在 bpo-34538 中貢獻。)

  • 當傳遞名稱 'root' 時, logging.getLogger() API 現在返回根日誌器,而以前它返回一個名為 'root' 的非根日誌器。這可能會影響使用者程式碼明確需要名為 'root' 的非根日誌器的情況,或者在名為 'root.py' 的某個頂級模組中使用 logging.getLogger(__name__) 例項化日誌器的情況。(由 Vinay Sajip 在 bpo-37742 中貢獻。)

  • 當傳遞不是 strPurePath 例項的物件時, PurePath 的除法處理現在返回 NotImplemented,而不是引發 TypeError。這允許建立不繼承自上述型別的相容類。(由 Roger Aiudi 在 bpo-34775 中貢獻)。

  • 從 Python 3.9.5 開始, ipaddress 模組不再接受 IPv4 地址字串中的任何前導零。前導零是模糊的,並且被某些庫解釋為八進位制表示法。例如,舊函式 socket.inet_aton() 將前導零視為八進位制表示法。glibc 實現的現代 inet_pton() 不接受任何前導零。(由 Christian Heimes 在 bpo-36384 中貢獻)。

  • codecs.lookup() 現在以與 encodings.normalize_encoding() 相同的方式規範化編碼名稱,只是 codecs.lookup() 還會將名稱轉換為小寫。例如, "latex+latin1" 編碼名稱現在規範化為 "latex_latin1"。(由 Jordon Xu 在 bpo-37751 中貢獻。)

C API 的變化

  • 自 Python 3.8 起, 堆分配型別 的例項(例如使用 PyType_FromSpec() 和類似 API 建立的例項)持有對其型別物件的引用。如 Python 3.8 的“C API 變更”中所述,對於絕大多數情況,不應有副作用,但對於具有自定義 tp_traverse 函式的型別,請確保堆分配型別的所有自定義 tp_traverse 函式都訪問物件的型別。

    示例

    int
    foo_traverse(PyObject *self, visitproc visit, void *arg)
    {
    // Rest of the traverse function
    #if PY_VERSION_HEX >= 0x03090000
        // This was not needed before Python 3.9 (Python issue 35810 and 40217)
        Py_VISIT(Py_TYPE(self));
    #endif
    }
    

    如果您的遍歷函式委託給其基類(或其他型別)的 tp_traverse,請確保 Py_TYPE(self) 僅被訪問一次。請注意,只有 堆型別 預期會在 tp_traverse 中訪問型別。

    例如,如果您的 tp_traverse 函式包含

    base->tp_traverse(self, visit, arg)
    

    然後新增

    #if PY_VERSION_HEX >= 0x03090000
        // This was not needed before Python 3.9 (bpo-35810 and bpo-40217)
        if (base->tp_flags & Py_TPFLAGS_HEAPTYPE) {
            // a heap type's tp_traverse already visited Py_TYPE(self)
        } else {
            Py_VISIT(Py_TYPE(self));
        }
    #else
    

    (有關更多資訊,請參見 bpo-35810bpo-40217。)

  • 函式 PyEval_CallObjectPyEval_CallFunctionPyEval_CallMethodPyEval_CallObjectWithKeywords 已棄用。請改用 PyObject_Call() 及其變體。(更多詳細資訊請參見 bpo-29548。)

CPython 位元組碼變更

  • 添加了 LOAD_ASSERTION_ERROR 操作碼,用於處理 assert 語句。以前,如果 AssertionError 異常被遮蔽,斷言語句將無法正常工作。(由 Zackery Spytz 在 bpo-34880 中貢獻。)

  • COMPARE_OP 操作碼已拆分為四個不同的指令

    • 用於富比較的 COMPARE_OP

    • 用於“is”和“is not”測試的 IS_OP

    • 用於“in”和“not in”測試的 CONTAINS_OP

    • 用於在“try-except”語句中檢查異常的 JUMP_IF_NOT_EXC_MATCH

    (由 Mark Shannon 在 bpo-39156 中貢獻。)

構建更改

  • configure 指令碼添加了 --with-platlibdir 選項:平臺特定庫目錄的名稱,儲存在新的 sys.platlibdir 屬性中。有關更多資訊,請參見 sys.platlibdir 屬性。(由 Jan Matějek, Matěj Cepl, Charalampos Stratakis 和 Victor Stinner 在 bpo-1294959 中貢獻。)

  • COUNT_ALLOCS 特殊構建宏已移除。(由 Victor Stinner 在 bpo-39489 中貢獻。)

  • 在非 Windows 平臺上,現在需要 setenv()unsetenv() 函式才能構建 Python。(由 Victor Stinner 在 bpo-39395 中貢獻。)

  • 在非 Windows 平臺上,建立 bdist_wininst 安裝程式現已正式不支援。(有關更多詳細資訊,請參見 bpo-10945。)

  • 從原始碼在 macOS 上構建 Python 時,如果非系統 Tcl 和 Tk 框架安裝在 /Library/Frameworks 中, _tkinter 現在會連結它們,就像在舊版 macOS 上一樣。如果透過使用 --enable-universalsdk-isysroot 顯式配置 macOS SDK,則只搜尋 SDK 本身。預設行為仍可透過 --with-tcltk-includes--with-tcltk-libs 覆蓋。(由 Ned Deily 在 bpo-34956 中貢獻。)

  • Python 現在可以為 Windows 10 ARM64 構建。(由 Steve Dower 在 bpo-33125 中貢獻。)

  • 現在在使用 --pgo 時會跳過某些單獨的測試。所涉及的測試顯著增加了 PGO 任務時間,並且可能無助於改進最終可執行檔案的最佳化。這使得任務速度提高了大約 15 倍。執行完整的單元測試套件很慢。此更改可能導致構建最佳化程度略低,因為執行的程式碼分支不會那麼多。如果您願意等待更慢的構建,可以使用 ./configure [..] PROFILE_TASK="-m test --pgo-extended" 恢復舊行為。我們不保證哪個 PGO 任務集能產生更快的構建。關注此問題的使用者應執行自己的相關基準測試,因為結果可能取決於環境、工作負載和編譯器工具鏈。(有關更多詳細資訊,請參見 bpo-36044bpo-37707。)

C API 更改

新特性

移植到 Python 3.9

  • PyInterpreterState.eval_framePEP 523)現在需要一個新的強制性 tstate 引數(PyThreadState*)。(由 Victor Stinner 在 bpo-38500 中貢獻。)

  • 擴充套件模組:如果請求了模組狀態但尚未分配,則不再呼叫 m_traversem_clearm_freePyModuleDef 函式。這發生在模組建立後立即以及模組執行之前(Py_mod_exec 函式)。更準確地說,如果 m_size 大於 0 且模組狀態(由 PyModule_GetState() 返回)為 NULL,則不呼叫這些函式。

    沒有模組狀態的擴充套件模組(m_size <= 0)不受影響。

  • 如果在子直譯器中呼叫 Py_AddPendingCall(),現在該函式計劃從子直譯器而不是主直譯器呼叫。每個子直譯器現在都有自己的計劃呼叫列表。(由 Victor Stinner 在 bpo-39984 中貢獻。)

  • 當使用 -E 選項時(如果 PyConfig.use_environment 設定為 0),Windows 登錄檔不再用於初始化 sys.path。這在 Windows 上嵌入 Python 時非常重要。(由 Zackery Spytz 在 bpo-8901 中貢獻。)

  • 全域性變數 PyStructSequence_UnnamedField 現在是一個常量,並引用一個常量字串。(由 Serhiy Storchaka 在 bpo-38650 中貢獻。)

  • PyGC_Head 結構現在是不透明的。它僅在內部 C API(pycore_gc.h)中定義。(由 Victor Stinner 在 bpo-40241 中貢獻。)

  • Py_UNICODE_COPY, Py_UNICODE_FILL, PyUnicode_WSTR_LENGTH, PyUnicode_FromUnicode(), PyUnicode_AsUnicode(), _PyUnicode_AsUnicodePyUnicode_AsUnicodeAndSize() 在 C 中被標記為已棄用。它們自 Python 3.3 起已被 PEP 393 棄用。(由 Inada Naoki 在 bpo-36346 中貢獻。)

  • Py_FatalError() 函式被宏替換,除非定義了 Py_LIMITED_API 宏,否則該宏會自動記錄當前函式的名稱。(由 Victor Stinner 在 bpo-39882 中貢獻。)

  • vectorcall 協議現在要求呼叫者只將字串作為關鍵字名稱傳遞。(有關更多資訊,請參見 bpo-37540。)

  • 許多宏和函式的實現細節現在被隱藏

    (有關更多詳細資訊,請參見 bpo-40170。)

已移除

  • pyfpe.h 中的 PyFPE_START_PROTECT()PyFPE_END_PROTECT() 宏從受限 C API 中排除。(由 Victor Stinner 在 bpo-38835 中貢獻。)

  • PyTypeObjecttp_print 槽已移除。它在 Python 2.7 及更早版本中用於將物件列印到檔案。自 Python 3.0 起,它已被忽略和未使用。(由 Jeroen Demeyer 在 bpo-36974 中貢獻。)

  • 受限 C API 中的更改(如果定義了 Py_LIMITED_API 宏)

    • 從受限 C API 中排除了以下函式

      • PyThreadState_DeleteCurrent() (由 Joannah Nanjekye 在 bpo-37878 中貢獻。)

      • _Py_CheckRecursionLimit

      • _Py_NewReference()

      • _Py_ForgetReference()

      • _PyTraceMalloc_NewReference()

      • _Py_GetRefTotal()

      • 在受限 C API 中從未起作用的垃圾桶機制。

      • PyTrash_UNWIND_LEVEL

      • Py_TRASHCAN_BEGIN_CONDITION

      • Py_TRASHCAN_BEGIN

      • Py_TRASHCAN_END

      • Py_TRASHCAN_SAFE_BEGIN

      • Py_TRASHCAN_SAFE_END

    • 將以下函式和定義移至內部 C API

      • _PyDebug_PrintTotalRefs()

      • _Py_PrintReferences()

      • _Py_PrintReferenceAddresses()

      • _Py_tracemalloc_config

      • _Py_AddToAllObjects() (特定於 Py_TRACE_REFS 構建)

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

  • 移除了 _PyRuntime.getframe 鉤子,並移除了 _PyThreadState_GetFrame 宏,該宏是 _PyRuntime.getframe 的別名。它們僅由內部 C API 公開。還移除了 PyThreadFrameGetter 型別。(由 Victor Stinner 在 bpo-39946 中貢獻。)

  • 從 C API 中移除了以下函式。明確呼叫 PyGC_Collect() 以清除所有空閒列表。(由 Inada Naoki 和 Victor Stinner 在 bpo-37340bpo-38896bpo-40428 中貢獻。)

    • PyAsyncGen_ClearFreeLists()

    • PyContext_ClearFreeList()

    • PyDict_ClearFreeList()

    • PyFloat_ClearFreeList()

    • PyFrame_ClearFreeList()

    • PyList_ClearFreeList()

    • PyMethod_ClearFreeList()PyCFunction_ClearFreeList():繫結的方法物件的空閒列表已移除。

    • PySet_ClearFreeList():集合空閒列表已在 Python 3.4 中移除。

    • PyTuple_ClearFreeList()

    • PyUnicode_ClearFreeList():Unicode 空閒列表已在 Python 3.3 中移除。

  • 移除了 _PyUnicode_ClearStaticStrings() 函式。(由 Victor Stinner 在 bpo-39465 中貢獻。)

  • 移除了 Py_UNICODE_MATCH。它已被 PEP 393 棄用,並且自 Python 3.3 起已失效。可以改用 PyUnicode_Tailmatch() 函式。(由 Inada Naoki 在 bpo-36346 中貢獻。)

  • 清理了已定義但沒有實現的介面標頭檔案。移除的公共 API 符號有:_PyBytes_InsertThousandsGroupingLocale_PyBytes_InsertThousandsGrouping_Py_InitializeFromArgs_Py_InitializeFromWideArgs_PyFloat_Repr_PyFloat_Digits_PyFloat_DigitsInitPyFrame_ExtendStack_PyAIterWrapper_TypePyNullImporter_TypePyCmpWrapper_TypePySortWrapper_TypePyNoArgsFunction。(由 Pablo Galindo Salgado 在 bpo-39372 中貢獻。)

Python 3.9.1 中的顯著更改

型別提示

typing.Literal 的行為已更改,以符合 PEP 586 並與 PEP 中指定的靜態型別檢查器的行為匹配。

  1. Literal 現在會刪除重複的引數。

  2. Literal 物件之間的相等比較現在與順序無關。

  3. Literal 比較現在遵循型別。例如, Literal[0] == Literal[False] 以前評估為 True。現在是 False。為了支援這一變化,內部使用的型別快取現在支援區分型別。

  4. 如果 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 中貢獻。)

macOS 11.0 (Big Sur) 和 Apple Silicon Mac 支援

自 3.9.1 版起,Python 現在完全支援在 macOS 11.0 (Big Sur) 和 Apple Silicon Mac(基於 ARM64 架構)上構建和執行。新的通用構建變體 universal2 現已推出,可在一個可執行檔案集中原生支援 ARM64Intel 64。現在還可以在當前版本的 macOS 上構建二進位制檔案,以部署到一系列舊版 macOS 版本(測試到 10.9),同時根據執行時使用的作業系統版本有條件地提供一些較新的 OS 功能和選項(“弱連結”)。

(由 Ronald Oussoren 和 Lawrence D’Anna 在 bpo-41100 中貢獻。)

Python 3.9.2 中的顯著更改

collections.abc

collections.abc.Callable 泛型現在會扁平化型別引數,類似於 typing.Callable 當前的做法。這意味著 collections.abc.Callable[[int, str], str]__args__ 將是 (int, str, str);以前是 ([int, str], str)。為了允許此更改, types.GenericAlias 現在可以被子類化,並且在對 collections.abc.Callable 型別進行下標操作時將返回一個子類。透過 typing.get_args()__args__ 訪問引數的程式碼需要考慮此更改。對於引數化 collections.abc.Callable 的無效形式,可能會發出 DeprecationWarning,這些形式在 Python 3.9.1 中可能悄無聲息地透過。此 DeprecationWarning 將在 Python 3.10 中變為 TypeError。(由 Ken Jin 在 bpo-42195 中貢獻。)

urllib.parse

早期的 Python 版本允許在 urllib.parse.parse_qs()urllib.parse.parse_qsl() 中使用 ;& 作為查詢引數分隔符。出於安全考慮,併為了符合新的 W3C 建議,此功能已更改為只允許一個分隔符鍵,預設值為 &。此更改也影響 cgi.parse()cgi.parse_multipart(),因為它們內部使用了受影響的函式。有關更多詳細資訊,請參見其各自的文件。(由 Adam Goldschmidt、Senthil Kumaran 和 Ken Jin 在 bpo-42967 中貢獻。)

Python 3.9.3 中的顯著更改

一項安全修復程式改變了 ftplib.FTP 的行為,使其在建立被動資料通道時不再信任遠端伺服器傳送的 IPv4 地址。我們改為重用 FTP 伺服器的 IP 地址。對於需要舊行為的特殊程式碼,請將 FTP 例項上的 trust_server_pasv_ipv4_address 屬性設定為 True。(參見 gh-87451)

Python 3.9.5 中的顯著更改

urllib.parse

URL 部分中存在換行符或製表符字元可能導致某些形式的攻擊。根據更新 RFC 3986 的 WHATWG 規範, urllib.parse 中的解析器會從 URL 中去除 ASCII 換行符 \n\r 和製表符 \t 字元,從而防止此類攻擊。刪除的字元由新的模組級變數 urllib.parse._UNSAFE_URL_BYTES_TO_REMOVE 控制。(請參見 gh-88048

3.9.14 中的顯著安全特性

在將數字轉換為其他進位制(如十進位制)時,如果字串形式的位數超過限制,則會引發 ValueError,以避免因演算法複雜性而導致的潛在拒絕服務攻擊。此限制適用於除了 2(二進位制)、4、8(八進位制)、16(十六進位制)或 32 以外的進位制。這是針對 CVE 2020-10735 的緩解措施。此限制可以透過環境變數、命令列標誌或 sys API 進行配置或停用。有關詳細資訊,請參閱整數字符串轉換長度限制文件。預設限制是字串形式的 4300 位。

3.9.17 中的顯著變化

tarfile

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