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警告多年。 例如,使用 collections.Mapping 而不是 collections.abc.Mapping 會發出 DeprecationWarning 自 2012 年釋出的 Python 3.3 起。

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

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

為了向後相容,在 collections 模組中,抽象基類 的別名,例如 collections.Mappingcollections.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 開發模式除錯構建 中,現在會檢查 *encoding* 和 *errors* 引數的字串編碼和解碼操作。 示例:open()str.encode()bytes.decode()

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

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

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

  • 改進了 typing 模組的幫助。 現在會顯示所有特殊形式和特殊泛型別名(例如 UnionList)的文件字串。 將 help() 與諸如 List[int] 之類的泛型別名一起使用將顯示相應具體型別(在這種情況下為 list)的幫助。(由 Serhiy Storchaka 在 bpo-40257 中貢獻。)

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

  • in 運算子和 contains()indexOf()countOf() 函式中,呼叫 __iter__ 方法時發生的意外錯誤不再被 TypeError 掩蓋。operator 模組。(由 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 節點添加了文件字串,其中包含用於構造該節點的 ASDL 簽名。(由 Batuhan Taskaya 在 bpo-39638 中貢獻。)

asyncio

由於重大的安全問題,不再支援 asyncio.loop.create_datagram_endpoint() 的 *reuse_address* 引數。這是因為 UDP 中套接字選項 SO_REUSEADDR 的行為。有關更多詳細資訊,請參閱 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()。它主要用於在單獨的執行緒中執行 IO 繫結函式,以避免阻塞事件迴圈,並且基本上作為 run_in_executor() 的高階版本工作,可以直接使用關鍵字引數。(由 Kyle Stanley 和 Yury Selivanov 在 bpo-32309 中貢獻。)

當由於超時而取消任務時,asyncio.wait_for() 現在將等待取消完成,即使在 *timeout* <= 0 的情況下,就像使用正超時一樣。(由 Elvis Pranskevichus 在 bpo-32751 中貢獻。)

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

compileall

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

為生成的 .pyc 檔案中的路徑操作添加了新選項:*stripdir*、*prependdir*、*limit_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 中貢獻。)

現在,只有在沒有可重用的空閒 worker 時,才會按需生成 ProcessPoolExecutor 中的 worker。這優化了啟動開銷,並減少了空閒 worker 造成的 CPU 時間浪費。(由 Kyle Stanley 在 bpo-39207 中貢獻。)

curses

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

datetime

isocalendar() 方法(針對 datetime.date)和 isocalendar() 方法(針對 datetime.datetime)現在返回 namedtuple(),而不是 tuple。(由 Donghee Na 在 bpo-24416 中貢獻。)

distutils

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

fcntl

添加了常量 F_OFD_GETLKF_OFD_SETLKF_OFD_SETLKW。(由 Donghee Na 在 bpo-38602 中貢獻。)

ftplib

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

gc

當垃圾收集器進行一次收集時,其中一些物件復活(在執行 finalizer 之後,可以從隔離的週期外部訪問它們),不要阻止收集所有仍然無法訪問的物件。(由 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 中貢獻。)

現在,按 Esc 鍵會關閉 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 更改為常規字典。(由 Inada Naoki 在 bpo-36350bpo-39775 中貢獻。)

ipaddress

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

可以使用 ipaddress.IPv6Address 解析作用域 IPv6 地址。如果存在,作用域區域 ID 可以透過 scope_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 中貢獻。)

signal

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

time

在 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 檔案時,現在會保留屬性內的空白字元。EOLN 不再被標準化為 "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 中貢獻。)

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

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

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

  • 優化了當另一個集合比基本集合大得多時 difference_update() 的效能。(由 Evgeny Kapun 建議,程式碼由 Michele Orrù 在 bpo-8425 中貢獻。)

  • Python 的小型物件分配器 (obmalloc.c) 現在允許(不超過)一個空的 arena 保留可用,以便立即重用,而無需將其返回給作業系統。這可以防止在簡單的迴圈中出現抖動,在簡單的迴圈中,arena 可能會在每次迭代時重新建立和銷燬。(由 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。基準測試指令碼以納秒為單位顯示時間。基準測試是在 Intel® Core™ i7-4960HQ 處理器 上測量的,該處理器執行的是在 python.org 上找到的 macOS 64 位版本。

已棄用

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

  • 移除了 ElementTreeElement 類中 ElementTree 模組的 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.BZ2File 的 *buffering* 引數。自 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 lock。對於 asyncio.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

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

Python API 中的更改

  • __import__()importlib.util.resolve_name() 現在會丟擲 ImportError 異常,而之前會丟擲 ValueError 異常。捕獲特定異常型別並支援 Python 3.9 及更早版本的呼叫者需要使用 except (ImportError, ValueError): 來捕獲兩種異常。

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

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

  • bz2.BZ2File 的 *compresslevel* 引數現在是僅限關鍵字的,因為 *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。此更改不影響其行為,因為自 Python 3.3 以來,Py_UNICODEwchar_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() 將前導零視為八進位制表示法。現代 inet_pton() 的 glibc 實現不接受任何前導零。(由 Christian Heimes 在 bpo-36384 中貢獻。)

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

C API 中的更改

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

    示例

    int
    foo_traverse(foo_struct *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
    }
    

    如果你的 traverse 函式委託給其基類(或其他型別)的 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 異常被覆蓋,則 assert 語句將無法正常工作。(由 Zackery Spytz 在 bpo-34880 中貢獻。)

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

    • COMPARE_OP 用於豐富比較

    • IS_OP 用於 'is' 和 'is not' 測試

    • CONTAINS_OP 用於 ‘in’ 和 ‘not in’ 測試。

    • JUMP_IF_NOT_EXC_MATCH 用於檢查 ‘try-except’ 語句中的異常。

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

  • 現在可以為 Windows 10 ARM64 構建 Python。(由 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_frame (PEP 523) 現在需要一個新的強制性 tstate 引數 (PyThreadState*)。(由 Victor Stinner 在 bpo-38500 中貢獻。)

  • 擴充套件模組:如果請求了模組狀態但尚未分配模組狀態,則不再呼叫 m_traversem_clearm_free 函式。這種情況發生在模組建立之後且執行模組之前(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_COPYPy_UNICODE_FILLPyUnicode_WSTR_LENGTHPyUnicode_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。)

已移除

  • 從受限 C API 中排除了 pyfpe.hPyFPE_START_PROTECT()PyFPE_END_PROTECT() 宏。(由 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

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

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

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

  3. Literal 比較現在會考慮型別。例如,Literal[0] == Literal[False] 之前會被評估為 True。現在它為 False。為了支援此更改,內部使用的型別快取現在支援區分型別。

  4. 如果 Literal 物件的任何引數不是 可雜湊的,則在進行相等性比較時,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) 和基於 ARM64 架構的 Apple Silicon Mac 上構建和執行。新的通用構建變體 universal2 現在可用於在同一組可執行檔案中原生支援 ARM64Intel 64。現在還可以在當前版本的 macOS 上構建二進位制檔案,以部署在各種較舊的 macOS 版本(已測試到 10.9)上,同時根據執行時使用的作業系統版本有條件地提供一些較新的作業系統功能和選項(“弱連結”)。

(由 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__ 訪問引數的程式碼需要考慮此更改。對於可能在 Python 3.9.1 中靜默透過的 collections.abc.Callable 的無效引數化形式,可能會發出 DeprecationWarning。此 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 中的顯著安全特性

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

3.9.17 中的顯著變化

tarfile

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