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
警告多年。 例如,使用 collections.Mapping
而不是 collections.abc.Mapping
會發出 DeprecationWarning
自 2012 年釋出的 Python 3.3 起。
使用 -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 中貢獻。)
對於所有非零的
n
,"".replace("", s, n)
現在返回s
而不是空字串。 現在它與"".replace("", s)
一致。 對於bytes
和bytearray
物件也有類似的更改。(由 Serhiy Storchaka 在 bpo-28029 中貢獻。)現在任何有效表示式都可以用作裝飾器。 以前,語法限制要大得多。 有關詳細資訊,請參閱 PEP 614。(由 Brandt Bucher 在 bpo-39702 中貢獻。)
改進了
typing
模組的幫助。 現在會顯示所有特殊形式和特殊泛型別名(例如Union
和List
)的文件字串。 將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-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 節點添加了文件字串,其中包含用於構造該節點的 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 中貢獻。)
從 ThreadPoolExecutor
和 ProcessPoolExecutor
中移除了守護執行緒。這提高了與子直譯器的相容性,並提高了它們關閉過程的可預測性。(由 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_GETLK
、F_OFD_SETLK
和 F_OFD_SETLKW
。(由 Donghee Na 在 bpo-38602 中貢獻。)
ftplib¶
如果為建構函式提供的超時時間為零,FTP
和 FTP_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_HINTS
、418 IM_A_TEAPOT
和 425 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¶
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
更改為常規字典。(由 Inada Naoki 在 bpo-36350 和 bpo-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-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 中貢獻。)
signal¶
公開了 Linux 特有的 signal.pidfd_send_signal()
,用於使用檔案描述符而不是 pid 向程序傳送訊號。(bpo-38712)
smtplib¶
SMTP
和 SMTP_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 內建函式 (
range
、tuple
、set
、frozenset
、list
、dict
) 現在透過使用 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 中貢獻。)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
和Element
類中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.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¶
本節列出了先前描述的更改和其他可能需要更改程式碼的錯誤修復。
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.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
。此更改不影響其行為,因為自 Python 3.3 以來,Py_UNICODE
是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()
將前導零視為八進位制表示法。現代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
函式
PyEval_CallObject
、PyEval_CallFunction
、PyEval_CallMethod
和PyEval_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-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 中貢獻。)向公共 API 添加了函式
PyObject_GC_IsTracked()
和PyObject_GC_IsFinalized()
,以允許查詢 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
函式。這種情況發生在模組建立之後且執行模組之前(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。)
已移除¶
從受限 C API 中排除了
pyfpe.h
的PyFPE_START_PROTECT()
和PyFPE_END_PROTECT()
宏。(由 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_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
構建)
刪除了
_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¶
typing.Literal
的行為已更改為符合 PEP 586,並匹配 PEP 中指定的靜態型別檢查器的行為。
Literal
現在會刪除重複的引數。Literal
物件之間的相等比較現在與順序無關。Literal
比較現在會考慮型別。例如,Literal[0] == Literal[False]
之前會被評估為True
。現在它為False
。為了支援此更改,內部使用的型別快取現在支援區分型別。如果
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
現在可用於在同一組可執行檔案中原生支援 ARM64
和 Intel 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(十進位制))中,int
和 str
之間的轉換,如果字串形式的位數超過限制,現在會引發 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 中貢獻。)