Python 3.9 中的新特性¶
- 編輯:
Łukasz Langa
本文解釋了 Python 3.9 相較於 3.8 的新特性。Python 3.9 於 2020 年 10 月 5 日釋出。有關完整詳細資訊,請參閱更新日誌。
參見
PEP 596 - Python 3.9 釋出時間表
摘要 – 釋出亮點¶
新語法功能
新的內建功能
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 模組(
_abc、audioop、_bz2、_codecs、_contextvars、_crypt、_functools、_json、_locale、math、operator、resource、time、_weakref)現在使用 PEP 489 定義的多階段初始化;許多標準庫模組(
audioop、ast、grp、_hashlib、pwd、_posixsubprocess、random、select、struct、termios、zlib)現在使用 PEP 384 定義的穩定 ABI。
新庫模組
釋出過程變更
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 命令列選項測試您的應用程式,以檢視 DeprecationWarning 和 PendingDeprecationWarning,甚至可以使用 -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'}
新的字串方法,用於刪除字首和字尾¶
已新增 str.removeprefix(prefix) 和 str.removesuffix(suffix),以便輕鬆從字串中刪除不需要的字首或字尾。相應的 bytes、bytearray 和 collections.UserString 方法也已新增。有關完整說明,請參閱PEP 616。(由 Dennis Sweeney 在bpo-39939中貢獻。)
標準集合中的型別提示泛型¶
在型別註解中,您現在可以使用內建的集合型別,例如 list 和 dict 作為泛型型別,而不是從 typing 中匯入相應的首字母大寫的型別(例如 List 或 Dict)。標準庫中的其他一些型別現在也是泛型的,例如 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中貢獻。)
"".replace("", s, n)現在對於所有非零n返回s而不是空字串。它現在與"".replace("", s)一致。bytes和bytearray物件也有類似的更改。(由 Serhiy Storchaka 在bpo-28029中貢獻。)任何有效的表示式現在都可以用作裝飾器。以前,語法更加嚴格。有關詳細資訊,請參閱PEP 614。(由 Brandt Bucher 在bpo-39702中貢獻。)
改進了
typing模組的幫助。現在為所有特殊形式和特殊泛型別名(如Union和List)顯示 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-41848 和 bpo-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 檔案中進行路徑操作的新選項: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中貢獻。)
從 ThreadPoolExecutor 和 ProcessPoolExecutor 中移除了守護執行緒。這改善了與子直譯器的相容性以及其關閉過程的可預測性。(由 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.date 的 isocalendar() 方法和 datetime.datetime 的 isocalendar() 方法現在返回 namedtuple() 而不是 tuple。(由 Donghee Na 在bpo-24416中貢獻。)
distutils¶
upload 命令現在建立 SHA2-256 和 Blake2b-256 雜湊摘要。它在阻止 MD5 摘要的平臺上跳過 MD5。(由 Christian Heimes 在bpo-40698中貢獻。)
fcntl¶
添加了常量 fcntl.F_OFD_GETLK、fcntl.F_OFD_SETLK 和 fcntl.F_OFD_SETLKW。(由 Donghee Na 在bpo-38602中貢獻。)
ftplib¶
FTP 和 FTP_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_HINTS、418 IM_A_TEAPOT 和 425 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¶
IMAP4 和 IMAP4_SSL 的建構函式現在具有一個可選的 timeout 引數。此外,open() 方法現在也具有一個可選的 timeout 引數。此更改已應用於 IMAP4_SSL 和 IMAP4_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.arguments 從 OrderedDict 更改為普通 dict。(由 Inada Naoki 在bpo-36350和bpo-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-39479和bpo-39648中貢獻。)
添加了 math.nextafter():返回 x 之後朝向 y 的下一個浮點值。(由 Victor Stinner 在bpo-39288中貢獻。)
添加了 math.ulp():返回浮點數最低有效位的值。(由 Victor Stinner 在bpo-39310中貢獻。)
multiprocessing¶
multiprocessing.SimpleQueue 類有一個新的 close() 方法,用於顯式關閉佇列。(由 Victor Stinner 在bpo-30966中貢獻。)
nntplib¶
NNTP 和 NNTP_SSL 現在,如果其建構函式給定的超時為零,則會引發 ValueError,以防止建立非阻塞套接字。(由 Donghee Na 在bpo-39259中貢獻。)
os¶
為 si_code 添加了 CLD_KILLED 和 CLD_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¶
POP3 和 POP3_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¶
SMTP 和 SMTP_SSL 現在,如果其建構函式給定的超時為零,則會引發 ValueError,以防止建立非阻塞套接字。(由 Donghee Na 在bpo-39259中貢獻。)
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 內建函式(
range、tuple、set、frozenset、list、dict)現在透過使用 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 中貢獻。)parser和symbol模組已棄用,並將在未來版本的 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 之後,該模組將限制其種子為None、int、float、str、bytes和bytearray。在未指定 mode 引數的情況下開啟
GzipFile檔案進行寫入已棄用。在未來的 Python 版本中,它將預設始終以讀取模式開啟。請指定 mode 引數以寫入方式開啟並消除警告。(由 Serhiy Storchaka 在 bpo-28286 中貢獻。)_tkinter.TkappType的split()方法已棄用,轉而使用行為更一致和可預測的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 中貢獻。)
ast類slice、Index和ExtSlice被視為已棄用,並將在未來的 Python 版本中移除。value本身應替代Index(value)。Tuple(slices, Load())應替代ExtSlice(slices)。(由 Serhiy Storchaka 在 bpo-34822 中貢獻。)ast類Suite、Param、AugLoad和AugStore被視為已棄用,並將在未來的 Python 版本中移除。它們在 Python 3 中未由解析器生成,也未被程式碼生成器接受。(由 Batuhan Taskaya 在 bpo-39639 和 bpo-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 版本中從標準庫中移除。考慮第三方替代方案,例如 LibCST 或 parso。(由 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_thread和dummy_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.Thread的isAlive()方法已移除。它自 Python 3.8 起已棄用。請改用is_alive()。(由 Donghee Na 在 bpo-37804 中貢獻。)ElementTree模組中ElementTree和Element類的getchildren()和getiterator()方法已移除。它們在 Python 3.2 中已棄用。請使用iter(x)或list(x)代替x.getchildren(),並使用x.iter()或list(x.iter())代替x.getiterator()。(由 Serhiy Storchaka 在 bpo-36543 中貢獻。)舊的
plistlibAPI 已移除,它自 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.Condition和asyncio.Semaphore也是如此。(由 Andrew Svetlov 在 bpo-34793 中貢獻。)sys.getcounts()函式、-X showalloccount命令列選項以及 C 結構PyConfig的show_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.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.FTP和ftplib.FTP_TLS類中,並且預設編碼已從 Latin-1 更改為 UTF-8,以遵循 RFC 2640。asyncio.loop.shutdown_default_executor()已新增到AbstractEventLoop,這意味著繼承自它的替代事件迴圈應該定義此方法。(由 Kyle Stanley 在 bpo-34037 中貢獻。)__future__模組中未來標誌的常量值已更新,以防止與編譯器標誌衝突。以前PyCF_ALLOW_TOP_LEVEL_AWAIT與CO_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 中貢獻。)當傳遞不是
str或PurePath例項的物件時,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
函式
PyEval_CallObject、PyEval_CallFunction、PyEval_CallMethod和PyEval_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-36044 和 bpo-37707。)
C API 更改¶
新特性¶
PEP 573:添加了
PyType_FromModuleAndSpec()以將模組與類關聯;PyType_GetModule()和PyType_GetModuleState()以檢索模組及其狀態;以及PyCMethod和METH_METHOD以允許方法訪問其定義的類。(由 Marcel Plch 和 Petr Viktorin 在 bpo-38787 中貢獻。)添加了
PyFrame_GetCode()函式:獲取幀程式碼。添加了PyFrame_GetBack()函式:獲取幀的下一個外部幀。(由 Victor Stinner 在 bpo-40421 中貢獻。)將
PyFrame_GetLineNumber()新增到受限 C API。(由 Victor Stinner 在 bpo-40421 中貢獻。)添加了
PyThreadState_GetInterpreter()和PyInterpreterState_Get()函式以獲取直譯器。添加了PyThreadState_GetFrame()函式以獲取 Python 執行緒狀態的當前幀。添加了PyThreadState_GetID()函式:獲取 Python 執行緒狀態的唯一識別符號。(由 Victor Stinner 在 bpo-39947 中貢獻。)向 C API 添加了新的公共
PyObject_CallNoArgs()函式,該函式呼叫不帶任何引數的可呼叫 Python 物件。它是呼叫不帶任何引數的可呼叫 Python 物件的最有效方式。(由 Victor Stinner 在 bpo-37194 中貢獻。)受限 C API 中的更改(如果定義了
Py_LIMITED_API宏)為受限 API 提供
Py_EnterRecursiveCall()和Py_LeaveRecursiveCall()作為常規函式。以前,它們被定義為宏,但這些宏在受限 C API 中無法編譯,因為受限 C API 無法訪問PyThreadState.recursion_depth欄位(該結構在受限 C API 中是不透明的)。PyObject_INIT()和PyObject_INIT_VAR()成為常規的“不透明”函式,以隱藏實現細節。
添加了
PyModule_AddType()函式,以幫助將型別新增到模組。(由 Donghee Na 在 bpo-40024 中貢獻。)添加了
PyObject_GC_IsTracked()和PyObject_GC_IsFinalized()函式到公共 API,以允許查詢 Python 物件是否當前正在被垃圾回收器跟蹤或是否已完成最終化。(由 Pablo Galindo Salgado 在 bpo-40241 中貢獻。)添加了
_PyObject_FunctionStr()以獲取函式類物件的友好字串表示形式。(由 Jeroen Demeyer 在 bpo-37645 中提交補丁。)添加了
PyObject_CallOneArg()以使用一個位置引數呼叫物件(由 Jeroen Demeyer 在 bpo-37483 中提交補丁。)
移植到 Python 3.9¶
PyInterpreterState.eval_frame(PEP 523)現在需要一個新的強制性 tstate 引數(PyThreadState*)。(由 Victor Stinner 在 bpo-38500 中貢獻。)擴充套件模組:如果請求了模組狀態但尚未分配,則不再呼叫
m_traverse、m_clear和m_free的PyModuleDef函式。這發生在模組建立後立即以及模組執行之前(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_AsUnicode和PyUnicode_AsUnicodeAndSize()在 C 中被標記為已棄用。它們自 Python 3.3 起已被 PEP 393 棄用。(由 Inada Naoki 在 bpo-36346 中貢獻。)Py_FatalError()函式被宏替換,除非定義了Py_LIMITED_API宏,否則該宏會自動記錄當前函式的名稱。(由 Victor Stinner 在 bpo-39882 中貢獻。)vectorcall 協議現在要求呼叫者只將字串作為關鍵字名稱傳遞。(有關更多資訊,請參見 bpo-37540。)
許多宏和函式的實現細節現在被隱藏
PyObject_IS_GC()宏已轉換為函式。PyObject_NEW()宏成為PyObject_New宏的別名,PyObject_NEW_VAR()宏成為PyObject_NewVar宏的別名。它們不再直接訪問PyTypeObject.tp_basicsize成員。PyObject_GET_WEAKREFS_LISTPTR()宏已轉換為函式:該宏直接訪問PyTypeObject.tp_weaklistoffset成員。PyObject_CheckBuffer()宏已轉換為函式:該宏直接訪問PyTypeObject.tp_as_buffer成員。PyIndex_Check()現在始終宣告為不透明函式以隱藏實現細節:移除了PyIndex_Check()宏。該宏直接訪問PyTypeObject.tp_as_number成員。
(有關更多詳細資訊,請參見 bpo-40170。)
已移除¶
將
pyfpe.h中的PyFPE_START_PROTECT()和PyFPE_END_PROTECT()宏從受限 C API 中排除。(由 Victor Stinner 在 bpo-38835 中貢獻。)PyTypeObject 的
tp_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_LEVELPy_TRASHCAN_BEGIN_CONDITIONPy_TRASHCAN_BEGINPy_TRASHCAN_ENDPy_TRASHCAN_SAFE_BEGINPy_TRASHCAN_SAFE_END
將以下函式和定義移至內部 C API
_PyDebug_PrintTotalRefs()_Py_PrintReferences()_Py_PrintReferenceAddresses()_Py_tracemalloc_config_Py_AddToAllObjects()(特定於Py_TRACE_REFS構建)
移除了
_PyRuntime.getframe鉤子,並移除了_PyThreadState_GetFrame宏,該宏是_PyRuntime.getframe的別名。它們僅由內部 C API 公開。還移除了PyThreadFrameGetter型別。(由 Victor Stinner 在 bpo-39946 中貢獻。)從 C API 中移除了以下函式。明確呼叫
PyGC_Collect()以清除所有空閒列表。(由 Inada Naoki 和 Victor Stinner 在 bpo-37340、bpo-38896 和 bpo-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_DigitsInit、PyFrame_ExtendStack、_PyAIterWrapper_Type、PyNullImporter_Type、PyCmpWrapper_Type、PySortWrapper_Type、PyNoArgsFunction。(由 Pablo Galindo Salgado 在 bpo-39372 中貢獻。)
Python 3.9.1 中的顯著更改¶
型別提示¶
typing.Literal 的行為已更改,以符合 PEP 586 並與 PEP 中指定的靜態型別檢查器的行為匹配。
Literal現在會刪除重複的引數。Literal物件之間的相等比較現在與順序無關。Literal比較現在遵循型別。例如,Literal[0] == Literal[False]以前評估為True。現在是False。為了支援這一變化,內部使用的型別快取現在支援區分型別。如果
Literal物件的任何引數不是 可雜湊的,它們現在將在相等比較期間引發TypeError異常。請注意,使用可變引數宣告Literal不會引發錯誤>>> from typing import Literal >>> Literal[{0}] >>> Literal[{0}] == Literal[{False}] Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: unhashable type: 'set'
(由 Yurii Karabas 在 bpo-42345 中貢獻。)
macOS 11.0 (Big Sur) 和 Apple Silicon Mac 支援¶
自 3.9.1 版起,Python 現在完全支援在 macOS 11.0 (Big Sur) 和 Apple Silicon Mac(基於 ARM64 架構)上構建和執行。新的通用構建變體 universal2 現已推出,可在一個可執行檔案集中原生支援 ARM64 和 Intel 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¶
tarfile和shutil.unpack_archive()中的提取方法新增了一個 filter 引數,允許限制可能令人意外或危險的 tar 功能,例如在目標目錄之外建立檔案。有關詳細資訊,請參閱 提取過濾器。在 Python 3.12 中,不帶 filter 引數的使用將顯示DeprecationWarning。在 Python 3.14 中,預設值將切換為'data'。(由 Petr Viktorin 在 PEP 706 中貢獻。)