Python 3.9 有什么新變化?

發(fā)布版本

3.12.0a0

日期

五月 26, 2022

編者

?ukasz Langa

本文介紹了 Python 3.9 相比 3.8 的新特性。 Python 3.9 發(fā)布于 2020 年 10 月 5 日。

詳情請參閱 更新日志。

參見

PEP 596 - Python 3.9 發(fā)布計(jì)劃

摘要 -- 發(fā)布重點(diǎn)?

新的語法特性:

  • PEP 584,為 dict 增加合并運(yùn)算符;

  • PEP 585,標(biāo)準(zhǔn)多項(xiàng)集中的類型標(biāo)注泛型。

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

新的內(nèi)置特性:

  • PEP 616,移除前綴和后綴的字符串方法。

標(biāo)準(zhǔn)庫中的新特性:

  • PEP 593,靈活函數(shù)和變量注解;

  • 添加了 os.pidfd_open() 以允許不帶競爭和信號的進(jìn)程管理。

解釋器的改進(jìn):

  • PEP 573,從 C 擴(kuò)展類型的方法快速訪問模塊狀態(tài);

  • PEP 617,CPython 現(xiàn)在使用基于 PEG 的新解析器;

  • 一些 Python 內(nèi)置類型(range、tuple、set、frozenset、list、dict)現(xiàn)已使用 PEP 590 vectorcall 加速;

  • 垃圾回收不會因恢復(fù)的對象而阻塞;

  • 一些 Python 模塊(_abc、audioop_bz2、_codecs、_contextvars_crypt、_functools、_json_localemathoperatorresource、time、_weakref)現(xiàn)已使用 PEP 489 中定義的多段初始化;

  • 一些標(biāo)準(zhǔn)庫模塊 (audioop、astgrp、_hashlibpwd、_posixsubprocessrandom、select、structtermios、zlib) 現(xiàn)已使用 PEP 384 中定義的穩(wěn)定 ABI。

新的庫模塊:

  • PEP 615,標(biāo)準(zhǔn)庫的 zoneinfo 模塊現(xiàn)已支持 IANA 時區(qū)數(shù)據(jù)庫;

  • 圖的拓?fù)渑判驅(qū)崿F(xiàn)現(xiàn)在已由新的 graphlib 模塊提供。

發(fā)布進(jìn)程的變化:

  • PEP 602,CPython 采用年度發(fā)布周期。

請檢查代碼中的 DeprecationWarning。?

Python 2.7 支持未終止時,為了實(shí)現(xiàn)向下兼容 Python 2.7,Python 3 保留了許多舊版功能。Python 2 的支持終止后,已經(jīng)移除了一部分向下兼容層,剩余部分很快也會被移除。這幾年,大部分兼容層都會觸發(fā) DeprecationWarning 警告。例如,2012 年發(fā)布 Python 3.3 后,用 collections.Mapping 替代 collections.abc.Mapping 就會觸發(fā) DeprecationWarning。

請用 -W default 命令行選項(xiàng)測試應(yīng)用程序來查看 DeprecationWarningPendingDeprecationWarning,甚至可以用 -W error 將它們視為錯誤。 可以用 警告過濾器 忽略來自第三方代碼的警告。

Python 3.9 是最后一個提供 Python 2 向下兼容層的版本,以給予 Python 項(xiàng)目維護(hù)者更多時間移除 Python 2 支持,添加 Python 3.9 支持。

collections 模塊中 抽象基類 的別名,例如 collections.abc.Mapping 的別名 collections.Mapping 會為向下兼容最后保留一個發(fā)行版。 這些內(nèi)容將在 Python 3.10 中移除。

更通俗的說法是,請?jiān)?Python 開發(fā)模式 下運(yùn)行測試,這樣做有助于讓代碼兼容 Python 的后續(xù)版本。

注:一些前期已棄用的內(nèi)容也將在此 Python 版本中移除。 詳見 移除 一節(jié)。

新的特性?

字典合并與更新運(yùn)算符?

合并 (|) 與更新 (|=) 運(yùn)算符已被加入內(nèi)置的 dict 類。 它們?yōu)楝F(xiàn)有的 dict.update{**d1, **d2} 字典合并方法提供了補(bǔ)充。

示例:

>>>
>>> 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 中的貢獻(xiàn)。)

新增用于移除前綴和后綴的字符串方法?

增加了 str.removeprefix(prefix)str.removesuffix(suffix) 用于方便地從字符串移除不需要的前綴或后綴。 也增加了 bytes, bytearray 以及 collections.UserString 的對應(yīng)方法。 請參閱 PEP 616 了解詳情。 (由 Dennis Sweeney 在 bpo-39939 中貢獻(xiàn)。)

標(biāo)準(zhǔn)多項(xiàng)集中的類型標(biāo)注泛型?

在類型標(biāo)注中現(xiàn)在你可以使用內(nèi)置多項(xiàng)集類型例如 listdict 作為通用類型而不必從 typing 導(dǎo)入對應(yīng)的大寫形式類型名 (例如 ListDict)。 標(biāo)準(zhǔn)庫中的其他一些類型現(xiàn)在同樣也是通用的,例如 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 中貢獻(xiàn)。)

新的解析器?

Python 3.9 使用于基于 PEG 的新解析器替代 LL(1)。 新解析器的性能與舊解析器大致相當(dāng),但 PEG 在設(shè)計(jì)新語言特性時的形式化比 LL(1) 更靈活。 我們將在 Python 3.10 及之后版本中開始使用這種靈活性。

ast 模塊會使用新解析器并會生成與舊解析器一致的 AST。

在 Python 3.10 中,舊解析器將被移除,依賴于它的所有功能也將被移除(主要是 parser 模塊,它早已被棄用)。 只有 在 Python 3.9 中,你可以使用命令行開關(guān) (-X oldparser) 或環(huán)境變量 (PYTHONOLDPARSER=1) 切換回 LL(1) 解析器。

請參閱 PEP 617 了解詳情。 (由 Guido van Rossum, Pablo Galindo 和 Lysandros Nikolaou 在 bpo-40334 中貢獻(xiàn)。)

其他語言特性修改?

  • __import__() 現(xiàn)在會引發(fā) ImportError 而不是 ValueError,后者曾經(jīng)會在相對導(dǎo)入超出其最高層級包時發(fā)生。 (由 Ngalim Siregar 在 bpo-37444 中貢獻(xiàn)。)

  • Python 現(xiàn)在會獲取命令行中指定的腳本文件名 (例如: python3 script.py) 的絕對路徑: __main__ 模塊的 __file__ 屬性將是一個絕對路徑,而不是相對路徑。 現(xiàn)在此路徑在當(dāng)前目錄通過 os.chdir() 被改變后仍將保持有效。 作為附帶效果,回溯信息也將在此情況下為 __main__ 模塊幀顯示絕對路徑。 (由 Victor Stinner 在 bpo-20443 中貢獻(xiàn)。)

  • Python 開發(fā)模式 以及 調(diào)試編譯版本 中,現(xiàn)在會針對字符串編碼和解碼操作檢查 encodingerrors 參數(shù)。 例如: open(), str.encode()bytes.decode()。

    默認(rèn)設(shè)置下,為保證性能,errors 參數(shù)只會在第一次發(fā)生編碼/解碼錯誤時被檢查,并且對于空字符串 encoding 參數(shù)有時會被忽略。 (由 Victor Stinner 在 bpo-37388 中貢獻(xiàn)。)

  • "".replace("", s, n) 對于所有非零的 n 都將返回 s 而不是空字符串。 現(xiàn)在此方法會與 "".replace("", s) 保持一致。 對于 bytesbytearray 對象也有類似的修改。 (由 Serhiy Storchaka 在 bpo-28029 中貢獻(xiàn)。)

  • 任何有效的表達(dá)式現(xiàn)在都可被用作 decorator。 在之前版本中,相關(guān)語法則更為嚴(yán)格。 請參閱 PEP 614 了解詳情。 (由 Brandt Bucher 在 bpo-39702 中貢獻(xiàn)。)

  • 改進(jìn)了 typing 模塊的幫助信息。 現(xiàn)在將為所有特殊形式和特殊通用別名 (例如 UnionList) 顯示文檔字符串。 使用 help() 時傳入通用別名例如 List[int] 將顯示對應(yīng)實(shí)體類型 (這里對應(yīng)的是 list) 的幫助信息。 (由 Serhiy Storchaka 在 bpo-40257 中貢獻(xiàn)。)

  • aclose() / asend() / athrow() 的并行運(yùn)行現(xiàn)在已被禁止,且 ag_running 現(xiàn)在會反映異步生成器的實(shí)際運(yùn)行狀態(tài)。 (由 Yury Selivanov 在 bpo-30773 中貢獻(xiàn)。)

  • 調(diào)用 __iter__ 方法時發(fā)生的非預(yù)期錯誤不會再被 in 運(yùn)算符以及 operatorcontains(), indexOf()countOf() 中的 TypeError 所掩蓋。 (由 Serhiy Storchaka 在 bpo-40824 中貢獻(xiàn)。)

  • 未加圓括號的 lambda 表達(dá)式不能再作為推導(dǎo)式和生成器表達(dá)式的 if 子句的表達(dá)式部分。 請參閱 bpo-41848bpo-43755 了解詳情。

新增模塊?

zoneinfo?

zoneinfo 模塊為標(biāo)準(zhǔn)庫引入了 IANA 時區(qū)數(shù)據(jù)庫。 它添加了 zoneinfo.ZoneInfo,這是一個基于系統(tǒng)時區(qū)數(shù)據(jù)的實(shí)體 datetime.tzinfo 實(shí)現(xiàn)。

示例:

>>>
>>> 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 數(shù)據(jù)庫的平臺的一個回退數(shù)據(jù)源,還以第一方軟件包的形式發(fā)布了 tzdata 模塊 -- 通過 PyPI 發(fā)行并由 CPython 核心團(tuán)隊(duì)維護(hù)。

參見

PEP 615 -- 在標(biāo)準(zhǔn)庫中支持 IANA 時區(qū)數(shù)據(jù)庫

PEP 由 Paul Ganssle 撰寫并實(shí)現(xiàn)

graphlib?

添加了新的 graphlib 模塊,其中包含 graphlib.TopologicalSorter 類來提供圖的拓?fù)渑判蚬δ堋?(由 Pablo Galindo, Tim Peters 和 Larry Hastings 在 bpo-17005 中貢獻(xiàn)。)

改進(jìn)的模塊?

ast?

indent 選項(xiàng)添加到 dump(),這允許它產(chǎn)生多行縮進(jìn)的輸出。 (由 Serhiy Storchaka 在 bpo-37995 中貢獻(xiàn)。)

添加了 ast.unparse() 作為 ast 模塊中的一個函數(shù),它可被用來反解析 ast.AST 對象并產(chǎn)生相應(yīng)的代碼字符串,當(dāng)它被解析時將會產(chǎn)生一個等價的 ast.AST 對象。 (由 Pablo Galindo 和 Batuhan Taskaya 在 bpo-38870 中貢獻(xiàn)。)

為 AST 節(jié)點(diǎn)添加了文檔字符串,其中包含 ASDL 簽名,可被用來構(gòu)造對應(yīng)的節(jié)點(diǎn)。 (由 Batuhan Taskaya 在 bpo-39638 中貢獻(xiàn)。)

asyncio?

出于重要的安全性考量,asyncio.loop.create_datagram_endpoint()reuse_address 形參不再被支持。 這是由 UDP 中的套接字選項(xiàng) SO_REUSEADDR 的行為導(dǎo)致的。 更多細(xì)節(jié)請參閱 loop.create_datagram_endpoint() 的文檔。 (由 Kyle Stanley, Antoine Pitrou 和 Yury Selivanov 在 bpo-37228 中貢獻(xiàn)。。)

添加了新的 coroutine shutdown_default_executor(),它可為等待 ThreadPoolExecutor 結(jié)束關(guān)閉的默認(rèn)執(zhí)行器安排關(guān)閉日程操作。 此外,asyncio.run() 已被更新以使用新的 coroutine。 (由 Kyle Stanley 在 bpo-34037 中貢獻(xiàn)。)

添加了 asyncio.PidfdChildWatcher,這是一個 Linux 專屬的子監(jiān)視器實(shí)現(xiàn),它負(fù)責(zé)輪詢進(jìn)程的文件描述符。 (bpo-38692)

添加了新的 coroutine asyncio.to_thread()。 它主要被用于在單獨(dú)線程中運(yùn)行 IO 密集型函數(shù)以避免阻塞事件循環(huán),實(shí)質(zhì)上就相當(dāng)于是 run_in_executor() 的高層級版本,可直接接受關(guān)鍵字參數(shù)。 (由 Kyle Stanley 和 Yury Selivanov 在 bpo-32309 中貢獻(xiàn)。)

當(dāng)由于超時而取消任務(wù)時,asyncio.wait_for() 現(xiàn)在將會等待直到也在 timeout 值 <= 0 的情況下完成取消。 就像 timeout 值為正數(shù)時一樣。 (由 Elvis Pranskevichus 在 bpo-32751 中貢獻(xiàn)。)

當(dāng)附帶 ssl.SSLSocket 套接字調(diào)用不兼容的方法時 asyncio 現(xiàn)在會引發(fā) TyperError。 (由 Ido Michael 在 bpo-37404 中貢獻(xiàn)。)

compileall?

為重復(fù)的 .pyc 文件添加了使用硬軟件的可能性: hardlink_dupes 形參以及 --hardlink-dupes 命令行選項(xiàng)。 (由 Lumír 'Frenzy' Balhar 在 bpo-40495 中貢獻(xiàn)。)

新增了一些用于在結(jié)果 .pyc 文件中操縱路徑的選項(xiàng): stripdir, prependdir, limit_sl_dest 形參以及 -s, -p, -e 命令行選項(xiàng)。 并使得為優(yōu)化等級多次指定選項(xiàng)成為可能。 (由 Lumír 'Frenzy' Balhar 在 bpo-38112 中貢獻(xiàn)。)

concurrent.futures?

將新的 cancel_futures 形參添加到 concurrent.futures.Executor.shutdown(),可以取消尚未開始運(yùn)行的所有掛起的 Future,而不必等待它們完成運(yùn)行再關(guān)閉執(zhí)行器。 (由 Kyle Stanley 在 bpo-39349 中貢獻(xiàn)。)

ThreadPoolExecutorProcessPoolExecutor 中移除了守護(hù)線程。 這改善與與子解釋器的兼容性及它們在關(guān)閉進(jìn)程時的可預(yù)測性。 (由 Kyle Stanley 在 bpo-39812 中貢獻(xiàn)。)

現(xiàn)在 ProcessPoolExecutor 中的工作進(jìn)程僅會在沒有可重用的空閑工作進(jìn)程時按需產(chǎn)生。 這優(yōu)化了啟動開銷并減少了由空閑工作進(jìn)程導(dǎo)致的 CPU 時間損失。 (由 Kyle Stanley 在 bpo-39207 中貢獻(xiàn)。)

curses?

增加了 curses.get_escdelay(), curses.set_escdelay(), curses.get_tabsize() 以及 curses.set_tabsize() 函數(shù)。(由 Anthony Sottile 在 bpo-38312 中貢獻(xiàn)。)

datetime?

datetime.dateisocalendar() 以及 datetime.datetimeisocalendar() 等方法現(xiàn)在將返回 namedtuple() 而不是 tuple。 (由 Dong-hee Na 在 bpo-24416 中貢獻(xiàn)。)

distutils?

upload 命令現(xiàn)在會創(chuàng)建 SHA2-256 和 Blake2b-256 哈希摘要。 它會在禁用 MD5 摘要的平臺上跳過 MD5。 (由 Christian Heimes 在 bpo-40698 中貢獻(xiàn)。)

fcntl?

增加了 F_OFD_GETLK, F_OFD_SETLKF_OFD_SETLKW 等常量。 (由 Dong-hee Na 在 bpo-38602 中貢獻(xiàn)。)

ftplib?

現(xiàn)在 FTPFTP_TLS 當(dāng)它們的構(gòu)造器所給定的超時參數(shù)為零以防止創(chuàng)建非阻塞套接字時會引發(fā) ValueError。 (由 Dong-hee Na 在 bpo-39259 中貢獻(xiàn)。)

gc?

當(dāng)垃圾回收器進(jìn)行某些復(fù)活對象的收集時(在終結(jié)器被執(zhí)行之后這些對象可以在隔離周期之外被訪問),不會阻止對所有仍然無法訪問的對象的收集。 (由 Pablo Galindo 和 Tim Peters 在 bpo-38379 中貢獻(xiàn)。)

增加了一個新的函數(shù) gc.is_finalized() 用來檢測一個對象是否已被垃圾回收器所終結(jié)。 (由 Pablo Galindo 在 bpo-39322 中貢獻(xiàn)。)

hashlib?

hashlib 模塊現(xiàn)在會在可能的情況下使用 OpenSSL 中的 SHA3 哈希和 SHAKE XOF。 (由 Christian Heimes 在 bpo-37630 中貢獻(xiàn)。)

內(nèi)置的哈希模塊現(xiàn)在可通過 ./configure --without-builtin-hashlib-hashes 禁用或通過 ./configure --with-builtin-hashlib-hashes=sha3,blake2 這樣的形式有選擇地啟用以強(qiáng)制使用基于 OpenSSL 的實(shí)現(xiàn)。 (由 Christian Heimes 在 bpo-40479 中貢獻(xiàn))

http?

添加 HTTP 狀態(tài)碼 103 EARLY_HINTS, 418 IM_A_TEAPOT425 TOO_EARLYhttp.HTTPStatus。 (由 Dong-hee Na 在 bpo-39509 以及 Ross Rhodes 在 bpo-39507 中貢獻(xiàn)。)

IDLE 與 idlelib?

添加了切換光標(biāo)閃爍停止的選項(xiàng)。 (由 Zackery Spytz 在 bpo-4603 中貢獻(xiàn)。)

Esc 鍵現(xiàn)在會關(guān)閉 IDLE 補(bǔ)全提示窗口。 (由 Johnny Najera 在 bpo-38944 中貢獻(xiàn)。)

添加關(guān)鍵字到模塊名稱補(bǔ)全列表。 (由 Terry J. Reedy 在 bpo-37765 中貢獻(xiàn)。)

New in 3.9 maintenance releases

Make IDLE invoke sys.excepthook() (when started without '-n'). User hooks were previously ignored. (Contributed by Ken Hilton in bpo-43008.)

上述修改已被反向移植到 3.8 維護(hù)發(fā)行版中。

Rearrange the settings dialog. Split the General tab into Windows and Shell/Ed tabs. Move help sources, which extend the Help menu, to the Extensions tab. Make space for new options and shorten the dialog. The latter makes the dialog better fit small screens. (Contributed by Terry Jan Reedy in bpo-40468.) Move the indent space setting from the Font tab to the new Windows tab. (Contributed by Mark Roseman and Terry Jan Reedy in bpo-33962.)

Apply syntax highlighting to .pyi files. (Contributed by Alex Waygood and Terry Jan Reedy in bpo-45447.)

imaplib?

現(xiàn)在 IMAP4IMAP4_SSL 的構(gòu)造器具有可選的 timeout 形參。 并且,現(xiàn)在 open() 方法也具有可選的 timeout 形參提供同樣的修改。 IMAP4_SSLIMAP4_stream 中被重載的方法也應(yīng)用了這個修改。 (由 Dong-hee Na 在 bpo-38615 中貢獻(xiàn)。)

增加了 imaplib.IMAP4.unselect()。 imaplib.IMAP4.unselect() 會釋放關(guān)聯(lián)到選定郵箱的服務(wù)器資源并將服務(wù)器返回到已認(rèn)證狀態(tài)。 此命令會執(zhí)行與 imaplib.IMAP4.close() 相同的動作,區(qū)別在于它不會從當(dāng)前選定郵箱中永久性地移除消息。 (由 Dong-hee Na 在 bpo-40375 中貢獻(xiàn)。)

importlib?

為提升與 import 語句的一致性,現(xiàn)在 importlib.util.resolve_name() 對于無效的相對導(dǎo)入嘗試會引發(fā) ImportError 而不是 ValueError。 (由 Ngalim Siregar 在 bpo-37444 中貢獻(xiàn)。)

發(fā)布不可變模塊對象的導(dǎo)入加載器除了發(fā)布單獨(dú)模塊以外現(xiàn)在也可以發(fā)布不可變包。 (由 Dino Viehland 在 bpo-39336 中貢獻(xiàn)。)

添加了帶有對包數(shù)據(jù)中子目錄支持的 importlib.resources.files() 函數(shù),與 importlib_resources 1.5 版的反向端口相匹配。(由 Jason R. Coombs 在 bpo-39791 中貢獻(xiàn)。)

來自 importlib_metadata 1.6.1 版的已更新 importlib.metadata。

inspect?

inspect.BoundArguments.arguments 已從 OrderedDict 改為常規(guī)字典。 (由 Inada Naoki 在 bpo-36350bpo-39775 中貢獻(xiàn)。)

ipaddress?

ipaddress 現(xiàn)在支持 IPv6 作用域地址(即帶有 %<scope_id> 前綴的 IPv6 地址)。

IPv6 作用域地址可使用 ipaddress.IPv6Address 來解析。 作用域的區(qū) ID 如果存在,可通過 scope_id 屬性來獲取。 (由 Oleksandr Pavliuk 在 bpo-34788 中貢獻(xiàn)。)

從 Python 3.9.5 開始 ipaddress 模塊不再接受 IPv4 地址字符串中有任何前綴的零。 (由 Christian Heimes 在 bpo-36384 中貢獻(xiàn)。)

math?

math.gcd() 函數(shù)進(jìn)行了擴(kuò)展以處理多個參數(shù)。 在之前版本中,它只支持兩個參數(shù)。 (由 Serhiy Storchaka 在 bpo-39648 中貢獻(xiàn)。)

增加了 math.lcm(): 返回指定參數(shù)的最小公倍數(shù)。 (由 Mark Dickinson, Ananthakrishnan 和 Serhiy Storchaka 在 bpo-39479bpo-39648 中貢獻(xiàn)。)

增加了 math.nextafter(): 返回從 xy 方向的下一個浮點(diǎn)數(shù)值。 (由 Victor Stinner 在 bpo-39288 中貢獻(xiàn)。)

增加了 math.ulp(): 返回一個浮點(diǎn)數(shù)的最小有效比特位。 (由 Victor Stinner 在 bpo-39310 中貢獻(xiàn)。)

multiprocessing?

multiprocessing.SimpleQueue 類新增了 close() 方法用來顯式地關(guān)閉隊(duì)列。 (由 Victor Stinner 在 bpo-30966 中貢獻(xiàn)。)

nntplib?

現(xiàn)在 NNTPNNTP_SSL 當(dāng)它們的構(gòu)造器所給定的超時參數(shù)為零以防止創(chuàng)建非阻塞套接字時會引發(fā) ValueError。 (由 Dong-hee Na 在 bpo-39259 中貢獻(xiàn)。)

os?

增加了 CLD_KILLEDCLD_STOPPED 作為 si_code。 (由 Dong-hee Na 在 bpo-38493 中貢獻(xiàn)。)

對外公開了 Linux 專屬的 os.pidfd_open() (bpo-38692) 和 os.P_PIDFD (bpo-38713) 用于文件描述符的進(jìn)程管理。

現(xiàn)在 os.unsetenv() 函數(shù)在 Windows 上也已可用。 (由 Victor Stinner 在 bpo-39413 中貢獻(xiàn)。)

現(xiàn)在 os.putenv()os.unsetenv() 函數(shù)將總是可用。 (由 Victor Stinner 在 bpo-39395 中貢獻(xiàn)。)

增加了 os.waitstatus_to_exitcode() 函數(shù):將等待狀態(tài)轉(zhuǎn)換為退出碼。 (由 Victor Stinner 在 bpo-40094 中貢獻(xiàn)。)

pathlib?

增加了 pathlib.Path.readlink(),其行為類似于 os.readlink()。 (由 Girts Folkmanis 在 bpo-30618 中貢獻(xiàn)。)

pdb?

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

poplib?

現(xiàn)在 POP3POP3_SSL 當(dāng)它們的構(gòu)造器所給定的超時參數(shù)為零以防止創(chuàng)建非阻塞套接字時會引發(fā) ValueError。 (由 Dong-hee Na 在 bpo-39259 中貢獻(xiàn)。)

pprint?

現(xiàn)在 pprint 能美化打印 types.SimpleNamespace。 (由 Carl Bordum Hansen 在 bpo-37376 中貢獻(xiàn)。)

pydoc?

文檔字符串的顯示現(xiàn)在不僅針對類、函數(shù)、方法等,也針對任何具有自己的 __doc__ 屬性的對象。 (由 Serhiy Storchaka 在 bpo-40257 中貢獻(xiàn)。)

random?

增加了新的 random.Random.randbytes 方法:生成隨機(jī)字節(jié)串。 (由 Victor Stinner 在 bpo-40286 中貢獻(xiàn)。)

signal?

對外公開了 Linux 專屬的 signal.pidfd_send_signal() 用于向使用文件描述符而非 pid 的進(jìn)程發(fā)送信號。 (bpo-38712)

smtplib?

現(xiàn)在 SMTPSMTP_SSL 當(dāng)它們的構(gòu)造器所給定的超時參數(shù)為零以防止創(chuàng)建非阻塞套接字時會引發(fā) ValueError。 (由 Dong-hee Na 在 bpo-39259 中貢獻(xiàn)。)

現(xiàn)在 LMTP 構(gòu)造器具有可選的 timeout 形參。 (由 Dong-hee Na 在 bpo-39329 中貢獻(xiàn)。)

socket?

socket 模塊現(xiàn)在會在 Linux 4.1 或更高版本上導(dǎo)出 CAN_RAW_JOIN_FILTERS 常量。 (由 Stefan Tatschner 和 Zackery Spytz 在 bpo-25780 中貢獻(xiàn)。)

現(xiàn)在 socket 模塊會在支持的平臺上支持 CAN_J1939 協(xié)議。 (由 Karl Ding 在 bpo-40291 上貢獻(xiàn)。)

現(xiàn)在 socket 模塊具有 socket.send_fds()socket.recv_fds() 函數(shù)。 (由 Joannah Nanjekye, Shinya Okano 和 Victor Stinner 在 bpo-28724 中貢獻(xiàn)。)

time?

On AIX, thread_time() is now implemented with thread_cputime() which has nanosecond resolution, rather than clock_gettime(CLOCK_THREAD_CPUTIME_ID) which has a resolution of 10 milliseconds. (Contributed by Batuhan Taskaya in bpo-40192)

sys?

增加了新的 sys.platlibdir 屬性:平臺專屬庫目錄的名稱。 它被用于構(gòu)建標(biāo)準(zhǔn)庫的路徑以及已安裝擴(kuò)展模塊的路徑。 它在大多數(shù)平臺上等于 "lib"。 在 Fedora 和 SuSE 上,它等于 64 位平臺上的 "lib64"。 (由 Jan Matějek, Matěj Cepl, Charalampos Stratakis 和 Victor Stinner 在 bpo-1294959 中貢獻(xiàn)。)

之前的版本中,sys.stderr 在非交互模式時是帶塊緩沖的。 現(xiàn)在 stderr 默認(rèn)總是為行緩沖的。 (由 Jendrik Seipp 在 bpo-13601 中貢獻(xiàn)。)

tracemalloc?

增加了 tracemalloc.reset_peak() 用于將跟蹤的內(nèi)存塊峰值大小設(shè)為當(dāng)前大小,以測量特定代碼段的峰值。 (由 Huon Wilson 在 bpo-40630 中貢獻(xiàn)。)

typing?

PEP 593 引入了一種 typing.Annotated 類型以使用上下文專屬的元數(shù)據(jù)來裝飾現(xiàn)有類型,并將新的 include_extras 形參添加到 typing.get_type_hints() 以在運(yùn)行時訪問元數(shù)據(jù)。 (由 Till Varoquaux 和 Konstantin Kashin 貢獻(xiàn)。)

unicodedata?

Unicode 數(shù)據(jù)庫已更新到 13.0.0 版。 (bpo-39926)。

venv?

venv 所提供的激活腳本現(xiàn)在總是會使用 __VENV_PROMPT__ 設(shè)置的值來一致地指明它們的自定義提示符。 在之前版本中某些腳本會無條件地使用 __VENV_PROMPT__,而另一些腳本只在其恰好被設(shè)置時(這是默認(rèn)情況)才會使用,還有的腳本會改用 __VENV_NAME__。 (由 Brett Cannon 在 bpo-37663 中貢獻(xiàn)。)

xml?

當(dāng)把 xml.etree.ElementTree 序列化為 XML 文件時屬性內(nèi)部的空白字符現(xiàn)在將被保留。 不同的行結(jié)束符不會再被正規(guī)化為 "n"。 這是對于如何解讀 XML 規(guī)范 2.11 節(jié)的相關(guān)討論的最終結(jié)果。 (由 Mefistotelis 在 bpo-39011 中貢獻(xiàn)。)

性能優(yōu)化?

  • 優(yōu)化了在推導(dǎo)式中為臨時變量賦值的慣用方式。 現(xiàn)在推導(dǎo)式中的 for y in [expr] 會與簡單賦值語句 y = expr 一樣快速。 例如:

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

    不同于 := 運(yùn)算符,這個慣用方式不會使變量泄露到外部作用域中。

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

  • 優(yōu)化了多線程應(yīng)用中的信號處理。 如果一個線程不是獲得信號的主線程,字節(jié)碼求值循環(huán)不會在每條字節(jié)碼指令上被打斷以檢查無法被處理的掛起信號。 只有主解釋器的主線程能夠處理信號。

    在之前版本中,字節(jié)碼求值循環(huán)會在每條指令上被打斷直到主線程處理了信號。 (由 Victor Stinner 在 bpo-40010 上貢獻(xiàn)。)

  • 在 FreeBSD 上使用 closefrom() 優(yōu)化了 subprocess 模塊。 (由 Ed Maste, Conrad Meyer, Kyle Evans, Kubilay Kocak 和 Victor Stinner 在 bpo-38061 中貢獻(xiàn)。)

  • PyLong_FromDouble() 對于匹配 long 的值執(zhí)行速度現(xiàn)在加快了 1.87 倍。 (由 Sergey Fedoseev d bpo-37986 中貢獻(xiàn)。)

  • 多個 Python 內(nèi)置類型 (range, tuple, set, frozenset, list, dict) 現(xiàn)在通過使用 PEP 590 向量調(diào)用協(xié)議得到加速。 (由 Dong-hee Na, Mark Shannon, Jeroen Demeyer 和 Petr Viktorin 在 bpo-37207 中貢獻(xiàn)。)

  • 當(dāng)另一集合遠(yuǎn)大于基礎(chǔ)集合的情況下優(yōu)化了 difference_update() 的性能。 (由 Evgeny Kapun 提議,由 Michele Orrù 在 bpo-8425 中貢獻(xiàn)代碼。)

  • Python 的小對象分配器 (obmalloc.c) 現(xiàn)在允許(至多)一個空位可用于立即重用,而不必將其返回給 OS。 這可以防止簡單循環(huán)中的多余消耗,在每次迭代中可以創(chuàng)建和銷毀全新的空位。 (由 Tim Peters 在 bpo-37257 中貢獻(xiàn)。)

  • 浮點(diǎn)數(shù)運(yùn)算中的 floor division 現(xiàn)在會有更好的性能。 并且此運(yùn)算的 ZeroDivisionError 的消息也已更新。 (由 Dong-hee Na 在 bpo-39434 中貢獻(xiàn)。)

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

以下是對從 Python 3.4 到 Python 3.9 的提升提升情況的總結(jié):

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

以上結(jié)果是由以下變量訪問基準(zhǔn)測試腳本所生成的: Tools/scripts/var_access_benchmark.py。 該基準(zhǔn)測試腳本以納秒為單位顯示時間。 基準(zhǔn)測試數(shù)據(jù)是在一塊 Intel? Core? i7-4960HQ 處理器 運(yùn)行從 python.org 獲取的 macOS 64 位編譯版本所得到的。

棄用?

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

  • 目前 math.factorial() 接受具有非負(fù)整數(shù)值的 float 實(shí)例 (如 5.0)。 對于非整數(shù)和負(fù)浮點(diǎn)數(shù)它會引發(fā) ValueError。 此行為現(xiàn)在已被棄用。 在未來的 Python 版本中對所有浮點(diǎn)數(shù)都將引發(fā) TypeError。 (由 Serhiy Storchaka 在 bpo-37315 中貢獻(xiàn)。)

  • parsersymbol 模塊已被棄用并將在未來的 Python 版本中移除。 對于大多數(shù)用例,用戶都可以使用 ast 模塊來控制抽象語法樹 (AST) 的生成和編譯階段。

  • 公有 C API 函數(shù) PyParser_SimpleParseStringFlags(), PyParser_SimpleParseStringFlagsFilename(), PyParser_SimpleParseFileFlags()PyNode_Compile() 已被棄用并將在 Python 3.10 版與舊解析器一起被移除。

  • 在布爾運(yùn)算中使用 NotImplemented 已被棄用,因?yàn)樗鼛缀醣囟ㄊ遣徽_的富比較運(yùn)算符實(shí)現(xiàn)的結(jié)果。 它將在未來的 Python 版本中引發(fā) TypeError。 (由 Josh Rosenberg 在 bpo-35712 中貢獻(xiàn)。)

  • random 模塊目前接受任何可哈希類型作為可能的種子值。 不幸的是,某些這樣的類型并不保證具有確定性的哈希值。 在 Python 3.9 之后,該模塊將限定其種子值為 None, int, float, str, bytes 以及 bytearray

  • 打開 GzipFile 文件用于寫入而不指定 mode 參數(shù)的特性已被棄用。 在未來的 Python 版本中將總是默認(rèn)打開用于讀取。 在打開文件用于寫入時請指定 mode 參數(shù)以靜默相關(guān)警告信息。 (由 Serhiy Storchaka 在 bpo-28286 中貢獻(xiàn)。)

  • 棄用了 _tkinter.TkappTypesplit() 方法而改用 splitlist() 方法,此方法具有更穩(wěn)定且可預(yù)測的行為。 (由 Serhiy Storchaka 在 bpo-38371 中貢獻(xiàn)。)

  • 將協(xié)程對象顯式傳遞給 asyncio.wait() 的做法已被棄用并且將在 3.11 版中被移除。 (由 Yury Selivanov 和 Kyle Stanley 在 bpo-34790 中貢獻(xiàn)。)

  • binhex4 和 hexbin4 標(biāo)準(zhǔn)現(xiàn)已被棄用。 binhex 模塊和下列 binascii 函數(shù)現(xiàn)已被棄用:

    • b2a_hqx(), a2b_hqx()

    • rlecode_hqx(), rledecode_hqx()

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

  • astslice, IndexExtSlice 被視為已棄用并將在未來的 Python 版本中被移除。 應(yīng)當(dāng)使用 value 本身而不再是 Index(value)。 應(yīng)當(dāng)使用 Tuple(slices, Load()) 而不再是 ExtSlice(slices)。 (由 Serhiy Storchaka 在 bpo-34822 中貢獻(xiàn)。)

  • astSuite, Param, AugLoadAugStore 被視為已棄用并將在未來的 Python 版本中被移除。 它們不會被解析器所生成且不會被 Python 3 中的代碼生成器所接受。 (由 Batuhan Taskaya 在 bpo-39639bpo-39969 中以及 Serhiy Storchaka 在 bpo-39988 中貢獻(xiàn)。)

  • PyEval_InitThreads()PyEval_ThreadsInitialized() 函數(shù)現(xiàn)已被棄用并將在 Python 3.11 中被移除。 調(diào)用 PyEval_InitThreads() 現(xiàn)在沒有任何效果。 自 Python 3.7 起 GIL 會由 Py_Initialize() 初始化。 (由 Victor Stinner 在 bpo-39877 中貢獻(xiàn)。)

  • 傳入 None 作為 shlex.split() 函數(shù)的第一個參數(shù)的做法已被棄用。 (由 Zackery Spytz 在 bpo-33262 中貢獻(xiàn)。)

  • smtpd.MailmanProxy() 現(xiàn)在已被棄用,因?yàn)樗跊]有外部模塊 mailman 的情況下無法使用。 (由 Samuel Colvin 在 bpo-35800 中貢獻(xiàn)。)

  • 現(xiàn)在 lib2to3 模塊將發(fā)出 PendingDeprecationWarning。 Python 3.9 已切換到 PEG 解析器 (參見 PEP 617),Python 3.10 可以會包含 lib2to3 的 LL(1) 解析器所不能解析的新語法。 lib2to3 模塊可能會在未來的 Python 版本中被移出標(biāo)準(zhǔn)庫。 請考慮使用第三方替換例如 LibCSTparso。 (由 Carl Meyer 在 bpo-40360 中貢獻(xiàn)。)

  • random.shuffle()random 形參已被棄用。 (由 Raymond Hettinger 在 bpo-40465 中貢獻(xiàn)。)

移除?

  • unittest.mock.__version__ 上的錯誤版本已經(jīng)被移除。

  • nntplib.NNTP: xpath()xgtitle() 方法已被移除。 這些方法自 Python 3.3 起已被棄用。 一般來說,這些擴(kuò)展都不再為 NNTP 服務(wù)管理員所支持或啟用。 對于 xgtitle(),請改用 nntplib.NNTP.descriptions()nntplib.NNTP.description()。 (由 Dong-hee Na 在 bpo-39366 中貢獻(xiàn)。)

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

  • 未寫入文檔的 sys.callstats() 函數(shù)已被移除。 自 Python 3.7 起它就已被棄用并且總是會返回 None。 它需要一個特殊的構(gòu)建選項(xiàng) CALL_PROFILE 而該選項(xiàng)在 Python 3.7 中已被移除。 (由 Victor Stinner 在 bpo-37414 中貢獻(xiàn)。)

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

  • C 函數(shù) PyImport_Cleanup() 已被移除。 它原本的文檔為: "清空模塊表。 僅限內(nèi)部使用。" (由 Victor Stinner 在 bpo-36710 中貢獻(xiàn)。)

  • _dummy_threaddummy_threading 模塊已被移除。 這些模塊自 Python 3.7 起已被棄用,它們需要線程支持。 (由 Victor Stinner 在 bpo-37312 中貢獻(xiàn)。)

  • aifc.open() 的別名 aifc.openfp(),sunau.open() 的別名 sunau.openfp(),以及 wave.open() 的別名 wave.openfp() 已被移除。 它們自 Python 3.7 起已被棄用。 (由 Victor Stinner 在 bpo-37320 中貢獻(xiàn)。)

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

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

  • 舊的 plistlib API 已被移除,它自 Python 3.4 起已被棄用。 請使用 load(), loads(), dump()dumps() 等函數(shù)。 此外,use_builtin_types 形參已被移除而總是會使用 bytes 對象。 (由 Jon Janzen 在 bpo-36409 中貢獻(xiàn)。)

  • C 函數(shù) PyGen_NeedsFinalizing 已被移除。 它未被寫入文檔、未經(jīng)測試,且自 PEP 442 實(shí)現(xiàn)之后未在 CPython 的任何地方被使用。 由 Joannah Nanjekye 提供補(bǔ)丁。 (由 Joannah Nanjekye 在 bpo-15088 中貢獻(xiàn)。)

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

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

  • bz2.BZ2Filebuffering 形參已被移除。 它自 Python 3.0 起即被忽略,使用它將會引發(fā) DeprecationWarning。 請傳入一個打開文件對象來控制文件的打開方式。 (由 Victor Stinner 在 bpo-39357 中貢獻(xiàn)。)

  • json.loads()encoding 形參已被移除。 它在 Python 3.1 中已被棄用和忽略;自 Python 3.8 起使用它將會引發(fā) DeprecationWarning。 (由 Inada Naoki 在 bpo-39377 中貢獻(xiàn)。)

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

  • sys.getcounts() 函數(shù),-X showalloccount 命令行選項(xiàng)以及 C 結(jié)構(gòu)體 PyConfigshow_alloc_count 字段已被移除。 它們需要使用定義了 COUNT_ALLOCS 宏的特殊 Python 編譯版本。 (由 Victor Stinner 在 bpo-39489 中貢獻(xiàn)。)

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

  • symtable.SymbolTable.has_exec() 方法已被移除。 它自 2006 年起已被棄用,當(dāng)被調(diào)用時僅會返回 False。 (由 Batuhan Taskaya 在 bpo-40208 中貢獻(xiàn)。)

  • asyncio.Task.current_task()asyncio.Task.all_tasks() 已被移除。 它們自 Python 3.7 起已被棄用,你可以改用 asyncio.current_task()asyncio.all_tasks()。 (由 Rémi Lapeyre 在 bpo-40967 中貢獻(xiàn)。)

  • html.parser.HTMLParser 類的 unescape() 方法已被移除(它自 Python 3.4 起已被棄用)。 應(yīng)當(dāng)使用 html.unescape() 來將字符引用轉(zhuǎn)換為對應(yīng)的 unicode 字符。

移植到 Python 3.9?

本節(jié)列出了先前描述的更改以及可能需要更改代碼的其他錯誤修正.

Python API 的變化?

  • __import__()importlib.util.resolve_name() 現(xiàn)在會引發(fā) ImportError 取代之前所引發(fā)的 ValueError。 捕獲特定異常類型并同時支持 Python 3.9 和更早版本的調(diào)用者將需要使用 except (ImportError, ValueError): 來同時捕獲兩者。

  • venv 激活腳本不再將 __VENV_PROMPT__ 被設(shè)為 "" 的情況作為特例處理。

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

  • bz2.BZ2Filecompresslevel 形參已成為僅限關(guān)鍵字形參,因?yàn)?buffering 形參已被移除。 (由 Victor Stinner 在 bpo-39357 中貢獻(xiàn)。)

  • 簡化了 AST 的抽取操作。 簡單索引將以它們的值來代表,擴(kuò)展切片將以元組形式來代表。 Index(value) 將返回 value 本身,ExtSlice(slices) 將返回 Tuple(slices, Load())。 (由 Serhiy Storchaka 在 bpo-34822 中貢獻(xiàn)。)

  • 當(dāng)使用了 -E-I 命令行參數(shù)時 importlib 模塊現(xiàn)在會忽略 PYTHONCASEOK 環(huán)境變量。

  • encoding 形參已作為僅限關(guān)鍵字形參被添加到 ftplib.FTPftplib.FTP_TLS 類,并且默認(rèn)編碼格式由 Latin-1 改為 UTF-8 以遵循 RFC 2640。

  • asyncio.loop.shutdown_default_executor() 已被添加到 AbstractEventLoop,這意味著繼承自它的替代事件循環(huán)應(yīng)當(dāng)定義此方法。 (由 Kyle Stanley 在 bpo-34037 中貢獻(xiàn)。)

  • 更新了 __future__ 模塊中未來特性旗標(biāo)的常量值以防止與編譯器旗標(biāo)相沖突。 在之前版本中 PyCF_ALLOW_TOP_LEVEL_AWAIT 會與 CO_FUTURE_DIVISION 發(fā)生沖突。 (由 Batuhan Taskaya 在 bpo-39562 中貢獻(xiàn)。)

  • array('u') 現(xiàn)在使用 wchar_t 作為 C 類型而不是 Py_UNICODE。 這個改變不會影響其行為,因?yàn)樽?Python 3.3 起 Py_UNICODEwchar_t 的別名。 (由 Inada Naoki 在 bpo-34538 中貢獻(xiàn)。)

  • 現(xiàn)在 logging.getLogger() API 當(dāng)傳入名稱 'root' 時將返回根日志記錄器,而在之前它則返回一個名為 'root' 的非根日志記錄器。 這可能會影響到用戶代碼明確希望使用一個名為 'root' 的非根日志記錄器,或在某個名為 'root.py' 的最高層級模塊中使用 logging.getLogger(__name__) 來實(shí)例化日志記錄器的情況。 (由 Vinay Sajip 在 bpo-37742 中貢獻(xiàn)。)

  • 現(xiàn)在 PurePath 的拆分處理當(dāng)傳入 strPurePath 的實(shí)例以外的對象時會返回 NotImplemented 而不是引發(fā) TypeError。 這將允許創(chuàng)建不繼承自上述類型的兼容類。 (由 Roger Aiudi 在 bpo-34775 中貢獻(xiàn)。)

  • 從 Python 3.9.5 開始 ipaddress 模塊不再接受 IPv4 地址字符串中有任何前綴的零。 前綴的零有歧義且會被某些庫解讀為八進(jìn)制數(shù)字。 例如舊版函數(shù) socket.inet_aton() 就瘵前綴的零視為八進(jìn)制數(shù)字。 最新 inet_pton() 的 glibc 實(shí)現(xiàn)則不接受任何前綴的零。 (由 Christian Heimes 在 bpo-36384 中貢獻(xiàn))。

  • codecs.lookup() 現(xiàn)在會以與 encodings.normalize_encoding() 相同的方式正規(guī)化編碼格式名稱,不同之處在于 codecs.lookup() 還會將名稱轉(zhuǎn)換為小寫形式。 例如``"latex+latin1"`` 編寫格式名稱現(xiàn)在會被正規(guī)化為 "latex_latin1"。 (由 Jordon Xu 在 bpo-37751 中貢獻(xiàn)。)

C API 的變化?

  • Instances of 堆分配類型 的實(shí)例(例如使用 PyType_FromSpec() 和類似 API 創(chuàng)建的實(shí)例)自 Python 3.8 起會帶有一個對其類型對象的引用。 正如 Python 3.8 的 "C API 的變化" 部分所述,對于大多數(shù)情況來說,這應(yīng)當(dāng)不會有任何副作用,但對于具有自定義 tp_traverse 函數(shù)的類型來說,則要確保所有堆分配類型的自定義 tp_traverse 函數(shù)可訪問對象的類型。

    示例:

    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
    }
    

    如果你的遍歷函數(shù)委托給了其基類(或其他類)的 tp_traverse,則要確保 Py_TYPE(self) 只被訪問一次。 請注意應(yīng)當(dāng)只有 堆類型 可訪問 tp_traverse 中的類型。

    舉例來說,如果你的 tp_traverse 函數(shù)包括以下內(nèi)容:

    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_CallObject, PyEval_CallFunction, PyEval_CallMethodPyEval_CallObjectWithKeywords 函數(shù)已被棄用。 請改用 PyObject_Call() 及其變化形式。 (詳情參見 bpo-29548。)

CPython 字節(jié)碼的改變?

  • 添加了 LOAD_ASSERTION_ERROR 操作碼用于處理 assert 語句。 在之前的版本中,如果 AssertionError 異常被屏蔽則 assert 語句將不能正常運(yùn)作。 (由 Zackery Spytz 在 bpo-34880 中貢獻(xiàn)。)

  • COMPARE_OP 操作碼已被拆分為四個單獨(dú)指令:

    • COMPARE_OP 用于富比較

    • IS_OP 用于 'is' 和 'is not' 檢測

    • CONTAINS_OP 用于 'in' 和 'not in' 檢測

    • JUMP_IF_NOT_EXC_MATCH 用于檢查 'try-except' 語句中的異常。

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

構(gòu)建的改變?

  • --with-platlibdir 選項(xiàng)添加到 configure 腳本:平臺專屬庫目錄的名稱,保存在新的 sys.platlibdir 屬性中。 請參閱 sys.platlibdir 屬性了解詳情。 (由 Jan Matějek, Matěj Cepl, Charalampos Stratakis 和 Victor Stinner 在 bpo-1294959 中貢獻(xiàn)。)

  • COUNT_ALLOCS 特殊構(gòu)建宏已被移除。 (由 Victor Stinner 在 bpo-39489 中貢獻(xiàn)。)

  • 在非 Windows 平臺上,現(xiàn)在需要用 setenv()unsetenv() 函數(shù)來構(gòu)建 Python。 (由 Victor Stinner 在 bpo-39395 中貢獻(xiàn)。)

  • 在非 Windows 平臺上,創(chuàng)建 bdist_wininst 安裝器現(xiàn)在已不受官方支持。 (詳情參見 bpo-10945。)

  • When building Python on macOS from source, _tkinter now links with non-system Tcl and Tk frameworks if they are installed in /Library/Frameworks, as had been the case on older releases of macOS. If a macOS SDK is explicitly configured, by using --enable-universalsdk or -isysroot, only the SDK itself is searched. The default behavior can still be overridden with --with-tcltk-includes and --with-tcltk-libs. (Contributed by Ned Deily in bpo-34956.)

  • Python 現(xiàn)在可以針對 Windows 10 ARM64 進(jìn)行編譯。 (由 Steve Dower 在 bpo-33125 中貢獻(xiàn)。)

  • 現(xiàn)在當(dāng)使用 --pgo 時一些單獨(dú)的測試會被跳過。 這些測試顯著增加了 PGO 任務(wù)的時間并且可能無助于提升最終可執(zhí)行文件的優(yōu)化程度。 這樣能使任務(wù)加速大約 15 倍。 運(yùn)行完整的單元測試是很慢的。 這個改變可能導(dǎo)致優(yōu)化程序稍差的構(gòu)建,因?yàn)閷⒈粓?zhí)行的代碼分支不夠多。 如果你愿意等待更緩慢的構(gòu)建,則可以使用 ./configure [..] PROFILE_TASK="-m test --pgo-extended" 來恢復(fù)舊版本的行為。 我們不保證哪個 PGO 任務(wù)集能產(chǎn)生更快的構(gòu)建。 關(guān)心此問題的用戶應(yīng)當(dāng)自行運(yùn)行相關(guān)基準(zhǔn)測試,因?yàn)榻Y(jié)果可能取決于具體環(huán)境、工作負(fù)載以及編譯工具鏈。 (請參閱 bpo-36044bpo-37707 了解詳情。)

C API 的改變?

新的特性?

  • PEP 573: 添加了 PyType_FromModuleAndSpec() 用于通過類來關(guān)聯(lián)一個模塊;PyType_GetModule()PyType_GetModuleState() 用于獲取模塊及其狀態(tài);以及 PyCMethodMETH_METHOD 用于允許一個方法訪問其定義所在的類。 (由 Marcel Plch 和 Petr Viktorin 在 bpo-38787 中貢獻(xiàn)。)

  • 增加了 PyFrame_GetCode() 函數(shù):獲取幀代碼。 增加了 PyFrame_GetBack() 函數(shù):獲取幀的下一個外部幀。 (由 Victor Stinner 在 bpo-40421 中貢獻(xiàn)。)

  • PyFrame_GetLineNumber() 添加到受限的 C API。 (由 Victor Stinner 在 bpo-40421 中貢獻(xiàn)。)

  • 增加了 PyThreadState_GetInterpreter()PyInterpreterState_Get() 函數(shù)用于獲取解釋器。 增加了 PyThreadState_GetFrame() 函數(shù)用于獲取 Python 線程狀態(tài)的當(dāng)前幀。 增加了 PyThreadState_GetID() 函數(shù):獲取 Python 線程狀態(tài)的唯一標(biāo)識符。 (由 Victor Stinner 在 bpo-39947 中貢獻(xiàn)。)

  • 將新的公有 PyObject_CallNoArgs() 函數(shù)添加到 C API,該函數(shù)可不帶任何參數(shù)調(diào)用一個 Python 可調(diào)用對象。 它是不帶參數(shù)調(diào)用 Python 可調(diào)用對象最有效率的方式。 (由 Victor Stinner 在 bpo-37194 中貢獻(xiàn)。)

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

    • 提供 Py_EnterRecursiveCall()Py_LeaveRecursiveCall() 作為常規(guī)函數(shù)用于受限 API。 在之前版本中是使用宏定義,但這些宏不能與無法訪問 PyThreadState.recursion_depth 字段的受限 C API 一同編譯(該結(jié)構(gòu)體在受限 C API 中是不透明的)。

    • PyObject_INIT()PyObject_INIT_VAR() 已成為常規(guī)“不透明”函數(shù)以隱藏實(shí)現(xiàn)細(xì)節(jié)。

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

  • 增加了 PyModule_AddType() 函數(shù)以協(xié)助將類型加入到模塊中。 (由 Dong-hee Na 在 bpo-40024 中貢獻(xiàn)。)

  • PyObject_GC_IsTracked()PyObject_GC_IsFinalized() 函數(shù)添加到公有 API 以允許分別查詢 Python 對象當(dāng)前是正在被追蹤還是已經(jīng)被垃圾回收器所終結(jié)。 (由 Pablo Galindo Salgado 在 bpo-40241 中貢獻(xiàn)。)

  • 增加了 _PyObject_FunctionStr() 以獲取函數(shù)類對象的用戶友好的表示形式。 (由 Jeroen Demeyer 在 bpo-37645 中修正。)

  • 增加了 PyObject_CallOneArg() 用于調(diào)用具有一個位置參數(shù)的對象(由 Jeroen Demeyer 在 bpo-37483 中修正。)

移植到 Python 3.9?

  • PyInterpreterState.eval_frame (PEP 523) 現(xiàn)在需要有新的強(qiáng)制性形參 tstate (PyThreadState*)。 (由 Victor Stinner 在 bpo-38500 中貢獻(xiàn)。)

  • 擴(kuò)展模塊: PyModuleDefm_traverse, m_clearm_free 等函數(shù)在模塊狀態(tài)被請求但尚未被分配時將不會再被調(diào)用。 這種情況出現(xiàn)在模塊被創(chuàng)建之后且模塊被執(zhí)行 (Py_mod_exec 函數(shù)) 之前的時刻。 更準(zhǔn)確地說,這些函數(shù)在 m_size 大于 0 并且模塊狀態(tài)(即 PyModule_GetState() 的返回值)為 NULL 時將不會被調(diào)用。

    沒有模塊狀態(tài)的擴(kuò)展模塊 (m_size <= 0) 不會受到影響。

  • 現(xiàn)在如果 Py_AddPendingCall() 是在子解釋器內(nèi)部被調(diào)用,該函數(shù)會被排入子解釋器的調(diào)用日程,而不是由主解釋器調(diào)用。 每個子解釋器現(xiàn)在都擁有它們自己的調(diào)用日程列表。 (由 Victor Stinner 在 bpo-39984 中貢獻(xiàn)。)

  • 當(dāng) -E 選項(xiàng)被使用 (如果 PyConfig.use_environment 設(shè)為 0) 時將不再使用 Windows 注冊表來初始化 sys.path。 這會影響在 Windows 上嵌入 Python 的操作。 (由 Zackery Spytz 在 bpo-8901 中貢獻(xiàn)。)

  • 全局變量 PyStructSequence_UnnamedField 現(xiàn)在為常量并且指向一個字符串常量。 (由 Serhiy Storchaka 在 bpo-38650 中貢獻(xiàn)。)

  • 現(xiàn)在 PyGC_Head 結(jié)構(gòu)是不透明的。 它只在內(nèi)部 C API (pycore_gc.h) 中定義。 (由 Victor Stinner 在 bpo-40241 中貢獻(xiàn)。)

  • Py_UNICODE_COPY, Py_UNICODE_FILL, PyUnicode_WSTR_LENGTH, PyUnicode_FromUnicode(), PyUnicode_AsUnicode(), _PyUnicode_AsUnicode 以及 PyUnicode_AsUnicodeAndSize() 在 C 中被標(biāo)記為已棄用。 它們自 Python 3.3 起就已被 PEP 393 棄用。 (由 Inada Naoki 在 bpo-36346 中貢獻(xiàn)。)

  • Py_FatalError() 函數(shù)會被一個自動記錄當(dāng)前函數(shù)名稱的宏所替代,除非已定義了 Py_LIMITED_API 宏。 (由 Victor Stinner 在 bpo-39882 中貢獻(xiàn)。)

  • vectorcall 協(xié)議現(xiàn)在要求調(diào)用者只傳入字符串作為鍵名。 (請參閱 bpo-37540 了解詳情。)

  • 多個宏和函數(shù)的實(shí)現(xiàn)細(xì)節(jié)現(xiàn)在已被隱藏:

    (詳情請參閱 bpo-40170。)

移除?

  • pyfpe.hPyFPE_START_PROTECT()PyFPE_END_PROTECT() 宏已從受限的 C API 中被排除。 (由 Victor Stinner 在 bpo-38835 中貢獻(xiàn)。)

  • PyTypeObjecttp_print 空位已被移除。 它在 Python 2.7 及之前的版本中被用來將對象打印到文件。 自 Python 3.0 起,它已被忽略并且不再使用。 (由 Jeroen Demeyer 在 bpo-36974 中貢獻(xiàn)。)

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

    • 以下函數(shù)已從受限 C API 中排除:

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

      • _Py_CheckRecursionLimit

      • _Py_NewReference()

      • _Py_ForgetReference()

      • _PyTraceMalloc_NewReference()

      • _Py_GetRefTotal()

      • 在受限 C API 中從未使用的垃圾箱機(jī)制。

      • PyTrash_UNWIND_LEVEL

      • Py_TRASHCAN_BEGIN_CONDITION

      • Py_TRASHCAN_BEGIN

      • Py_TRASHCAN_END

      • Py_TRASHCAN_SAFE_BEGIN

      • Py_TRASHCAN_SAFE_END

    • 已將下列函數(shù)和定義移至內(nèi)部 C API:

      • _PyDebug_PrintTotalRefs()

      • _Py_PrintReferences()

      • _Py_PrintReferenceAddresses()

      • _Py_tracemalloc_config

      • _Py_AddToAllObjects() (Py_TRACE_REFS 構(gòu)建專屬)

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

  • 移除了 _PyRuntime.getframe 鉤子并移除了 _PyThreadState_GetFrame 宏,該宏是 _PyRuntime.getframe 的一個別名。 它們僅由內(nèi)部 C API 對外公開。 同樣地移除了 PyThreadFrameGetter 類型。 (由 Victor Stinner 在 bpo-39946 中貢獻(xiàn)。)

  • 從 C API 移除了下列函數(shù)。 請顯式地調(diào)用 PyGC_Collect() 來清空所有自由列表。 (由 Inada Naoki 和 Victor Stinner 在 bpo-37340, bpo-38896bpo-40428 中貢獻(xiàn)。)

    • 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() 函數(shù)。 (由 Victor Stinner 在 bpo-39465 中貢獻(xiàn)。)

  • 移除了 Py_UNICODE_MATCH。 它已被 PEP 393 所棄用,并自 Python 3.3 起不再可用。 可以改用 PyUnicode_Tailmatch() 函數(shù)。 (由 Inada Naoki 在 bpo-36346 中貢獻(xiàn)。)

  • 清除了已定義但未實(shí)現(xiàn)的接口的頭文件。 被移除了公共 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 中貢獻(xiàn)。)

Python 3.9.1 中的重要變化?

typing?

typing.Literal 的行為被改為遵循 PEP 586 并匹配該 PEP 所描述的靜態(tài)類型檢查器的行為。

  1. Literal 現(xiàn)在將是去重復(fù)的形參。

  2. Literal 對象間的相等性比較現(xiàn)在將是順序無關(guān)的。

  3. Literal 比較現(xiàn)在會考慮類型。 例如 Literal[0] == Literal[False] 之前的結(jié)果值為 True。 現(xiàn)在則為 False。 為支持此改變,內(nèi)部使用的類型緩存現(xiàn)在也支持區(qū)分類型。

  4. 現(xiàn)在如果有任何一個參數(shù)不為 hashable,Literal 對象將在相等性比較期間引發(fā) TypeError。 請注意使用可變參數(shù)聲明 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 中貢獻(xiàn)。)

macOS 11.0 (Big Sur) 與 Apple Silicon Mac 支持?

對于 3.9.1 版來說,Python 現(xiàn)在完全支持在 macOS 11.0 (Big Sur) 和 Apple Silicon Macs (基于 ARM64 架構(gòu)) 上構(gòu)建和運(yùn)行。 現(xiàn)在提供了一個新的通用構(gòu)建類型 universal2,用于在一組可執(zhí)行文件上原生支持 ARM64Intel 64。 二進(jìn)制文件現(xiàn)在也可以在當(dāng)前版本的 macOS 上編譯以部署到多種較舊的 macOS 版本上 (已測試 10.9),同時會基于運(yùn)行時所使用的操作系統(tǒng)版本讓某些較新的 OS 功能和選項(xiàng)有條件地可用 ("弱鏈接") 。

(由 Ronald Oussoren 和 Lawrence D'Anna 在 bpo-41100 中貢獻(xiàn)。)

Python 3.9.2 中的重要變化?

collections.abc?

現(xiàn)在 collections.abc.Callable 泛型會將類型形參展平,類似于 typing.Callable 當(dāng)前所做的那樣。 這意味著 collections.abc.Callable[[int, str], str]__args__ 將為 (int, str, str);之前則為 ([int, str], str)。 為了允許這個改變,types.GenericAlias 現(xiàn)在可以被子類化,并且在抽取 collections.abc.Callable 類型時將返回一個子類。 通過 typing.get_args()__args__ 訪問參數(shù)的代碼需要考慮到這個改變。 對于無效的 collections.abc.Callable 參數(shù)化形式可能會發(fā)出 DeprecationWarning,這在 Python 3.9.1 中可能會靜默地傳遞。 這個 DeprecationWarning 將在 Python 3.10 中變?yōu)?TypeError。 (由 Ken Jin 在 bpo-42195 中貢獻(xiàn)。)

urllib.parse?

早先的 Python 版本允許使用 ;& 作為 urllib.parse.parse_qs()urllib.parse.parse_qsl() 中 query 形參的分隔鍵。 出于安全考慮,也為了遵循更新的 W3C 推薦設(shè)置,這已被改為只允許單個分隔鍵,默認(rèn)為 &。 這一改變還會影響 cgi.parse()cgi.parse_multipart() 因?yàn)樗鼈冊趦?nèi)部使用了受影響的函數(shù)。 要了解更多細(xì)節(jié),請查看它們各自的文檔。 (由 Adam Goldschmidt, Senthil Kumaran 和 Ken Jin 在 bpo-42967 中貢獻(xiàn)。)