Python 3.9 有什么新變化?

發(fā)布版本

3.12.0a0

日期

五月 26, 2022

編者

?ukasz Langa

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

詳情請參閱 更新日志。

參見(jiàn)

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

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

新的語(yǔ)法特性:

  • PEP 584,為 dict 增加合并運算符;

  • PEP 585,標準多項集中的類(lèi)型標注泛型。

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

新的內置特性:

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

標準庫中的新特性:

  • PEP 593,靈活函數和變量注解;

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

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

  • PEP 573,從 C 擴展類(lèi)型的方法快速訪(fǎng)問(wèn)模塊狀態(tài);

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

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

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

  • 一些 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 615,標準庫的 zoneinfo 模塊現已支持 IANA 時(shí)區數據庫;

  • 圖的拓撲排序實(shí)現現在已由新的 graphlib 模塊提供。

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

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

請檢查代碼中的 DeprecationWarning。?

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

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

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

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

更通俗的說(shuō)法是,請在 Python 開(kāi)發(fā)模式 下運行測試,這樣做有助于讓代碼兼容 Python 的后續版本。

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

新的特性?

字典合并與更新運算符?

合并 (|) 與更新 (|=) 運算符已被加入內置的 dict 類(lèi)。 它們?yōu)楝F有的 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'}

詳見(jiàn) PEP 584。(Brandt Bucher 在 bpo-36144 中的貢獻。)

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

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

標準多項集中的類(lèi)型標注泛型?

在類(lèi)型標注中現在你可以使用內置多項集類(lèi)型例如 listdict 作為通用類(lèi)型而不必從 typing 導入對應的大寫(xiě)形式類(lèi)型名 (例如 ListDict)。 標準庫中的其他一些類(lèi)型現在同樣也是通用的,例如 queue.Queue。

示例:

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

詳見(jiàn) PEP 585。(由 Guido van Rossum、Ethan Smith 和 Batuhan Ta?kaya 在 bpo-39481 中貢獻。)

新的解析器?

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

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

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

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

其他語(yǔ)言特性修改?

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

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

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

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

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

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

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

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

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

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

新增模塊?

zoneinfo?

zoneinfo 模塊為標準庫引入了 IANA 時(shí)區數據庫。 它添加了 zoneinfo.ZoneInfo,這是一個(gè)基于系統時(shí)區數據的實(shí)體 datetime.tzinfo 實(shí)現。

示例:

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

參見(jiàn)

PEP 615 -- 在標準庫中支持 IANA 時(shí)區數據庫

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

graphlib?

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

改進(jìn)的模塊?

ast?

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

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

為 AST 節點(diǎn)添加了文檔字符串,其中包含 ASDL 簽名,可被用來(lái)構造對應的節點(diǎn)。 (由 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 中貢獻。。)

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

添加了 asyncio.PidfdChildWatcher,這是一個(gè) Linux 專(zhuān)屬的子監視器實(shí)現,它負責輪詢(xún)進(jìn)程的文件描述符。 (bpo-38692)

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

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

當附帶 ssl.SSLSocket 套接字調用不兼容的方法時(shí) asyncio 現在會(huì )引發(fā) TyperError。 (由 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 命令行選項。 并使得為優(yōu)化等級多次指定選項成為可能。 (由 Lumír 'Frenzy' Balhar 在 bpo-38112 中貢獻。)

concurrent.futures?

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

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

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

curses?

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

datetime?

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

distutils?

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

fcntl?

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

ftplib?

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

gc?

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

增加了一個(gè)新的函數 gc.is_finalized() 用來(lái)檢測一個(gè)對象是否已被垃圾回收器所終結。 (由 Pablo Galindo 在 bpo-39322 中貢獻。)

hashlib?

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

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

http?

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

IDLE 與 idlelib?

添加了切換光標閃爍停止的選項。 (由 Zackery Spytz 在 bpo-4603 中貢獻。)

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

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

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 維護發(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?

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

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

importlib?

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

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

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

來(lái)自 importlib_metadata 1.6.1 版的已更新 importlib.metadata。

inspect?

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

ipaddress?

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

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

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

math?

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

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

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

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

multiprocessing?

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

nntplib?

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

os?

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

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

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

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

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

pathlib?

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

pdb?

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

poplib?

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

pprint?

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

pydoc?

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

random?

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

signal?

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

smtplib?

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

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

socket?

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

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

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

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 屬性:平臺專(zhuān)屬庫目錄的名稱(chēng)。 它被用于構建標準庫的路徑以及已安裝擴展模塊的路徑。 它在大多數平臺上等于 "lib"。 在 Fedora 和 SuSE 上,它等于 64 位平臺上的 "lib64"。 (由 Jan Matějek, Matěj Cepl, Charalampos Stratakis 和 Victor Stinner 在 bpo-1294959 中貢獻。)

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

tracemalloc?

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

typing?

PEP 593 引入了一種 typing.Annotated 類(lèi)型以使用上下文專(zhuān)屬的元數據來(lái)裝飾現有類(lèi)型,并將新的 include_extras 形參添加到 typing.get_type_hints() 以在運行時(shí)訪(fǎng)問(wèn)元數據。 (由 Till Varoquaux 和 Konstantin Kashin 貢獻。)

unicodedata?

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

venv?

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

xml?

當把 xml.etree.ElementTree 序列化為 XML 文件時(shí)屬性?xún)炔康目瞻鬃址F在將被保留。 不同的行結束符不會(huì )再被正規化為 "n"。 這是對于如何解讀 XML 規范 2.11 節的相關(guān)討論的最終結果。 (由 Mefistotelis 在 bpo-39011 中貢獻。)

性能優(yōu)化?

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

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

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

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

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

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

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

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

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

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

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

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

  • 使用 UTF-8 和 ascii 編解碼器解碼短 ASCII 字符串現在會(huì )加快大約 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

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

棄用?

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

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

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

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

  • 在布爾運算中使用 NotImplemented 已被棄用,因為它幾乎必定是不正確的富比較運算符實(shí)現的結果。 它將在未來(lái)的 Python 版本中引發(fā) TypeError。 (由 Josh Rosenberg 在 bpo-35712 中貢獻。)

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

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

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

  • 將協(xié)程對象顯式傳遞給 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 類(lèi) slice, IndexExtSlice 被視為已棄用并將在未來(lái)的 Python 版本中被移除。 應當使用 value 本身而不再是 Index(value)。 應當使用 Tuple(slices, Load()) 而不再是 ExtSlice(slices)。 (由 Serhiy Storchaka 在 bpo-34822 中貢獻。)

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

  • PyEval_InitThreads()PyEval_ThreadsInitialized() 函數現已被棄用并將在 Python 3.11 中被移除。 調用 PyEval_InitThreads() 現在沒(méi)有任何效果。 自 Python 3.7 起 GIL 會(huì )由 Py_Initialize() 初始化。 (由 Victor Stinner 在 bpo-39877 中貢獻。)

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

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

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

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

移除?

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

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

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

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

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

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

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

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

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

  • ElementTree 模塊中 ElementTreeElement 等類(lèi)的 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 形參已被移除而總是會(huì )使用 bytes 對象。 (由 Jon Janzen 在 bpo-36409 中貢獻。)

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

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

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

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

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

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

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

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

  • symtable.SymbolTable.has_exec() 方法已被移除。 它自 2006 年起已被棄用,當被調用時(shí)僅會(huì )返回 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 類(lèi)的 unescape() 方法已被移除(它自 Python 3.4 起已被棄用)。 應當使用 html.unescape() 來(lái)將字符引用轉換為對應的 unicode 字符。

移植到 Python 3.9?

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

Python API 的變化?

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

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

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

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

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

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

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

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

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

  • array('u') 現在使用 wchar_t 作為 C 類(lèi)型而不是 Py_UNICODE。 這個(gè)改變不會(huì )影響其行為,因為自 Python 3.3 起 Py_UNICODEwchar_t 的別名。 (由 Inada Naoki 在 bpo-34538 中貢獻。)

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

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

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

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

C API 的變化?

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

    示例:

    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
    }
    

    如果你的遍歷函數委托給了其基類(lèi)(或其他類(lèi))的 tp_traverse,則要確保 Py_TYPE(self) 只被訪(fǎng)問(wèn)一次。 請注意應當只有 堆類(lèi)型 可訪(fǎng)問(wèn) tp_traverse 中的類(lèi)型。

    舉例來(lái)說(shuō),如果你的 tp_traverse 函數包括以下內容:

    base->tp_traverse(self, visit, arg)
    

    則要添加:

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

    (參閱 bpo-35810bpo-40217 了解更多信息。)

  • PyEval_CallObject, PyEval_CallFunction, PyEval_CallMethodPyEval_CallObjectWithKeywords 函數已被棄用。 請改用 PyObject_Call() 及其變化形式。 (詳情參見(jiàn) bpo-29548。)

CPython 字節碼的改變?

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

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

    • COMPARE_OP 用于富比較

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

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

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

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

構建的改變?

  • --with-platlibdir 選項添加到 configure 腳本:平臺專(zhuān)屬庫目錄的名稱(chēng),保存在新的 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() 函數來(lái)構建 Python。 (由 Victor Stinner 在 bpo-39395 中貢獻。)

  • 在非 Windows 平臺上,創(chuàng )建 bdist_wininst 安裝器現在已不受官方支持。 (詳情參見(jià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 現在可以針對 Windows 10 ARM64 進(jìn)行編譯。 (由 Steve Dower 在 bpo-33125 中貢獻。)

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

C API 的改變?

新的特性?

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

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

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

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

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

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

    • 提供 Py_EnterRecursiveCall()Py_LeaveRecursiveCall() 作為常規函數用于受限 API。 在之前版本中是使用宏定義,但這些宏不能與無(wú)法訪(fǎng)問(wèn) PyThreadState.recursion_depth 字段的受限 C API 一同編譯(該結構體在受限 C API 中是不透明的)。

    • PyObject_INIT()PyObject_INIT_VAR() 已成為常規“不透明”函數以隱藏實(shí)現細節。

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

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

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

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

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

移植到 Python 3.9?

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

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

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

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

  • -E 選項被使用 (如果 PyConfig.use_environment 設為 0) 時(shí)將不再使用 Windows 注冊表來(lái)初始化 sys.path。 這會(huì )影響在 Windows 上嵌入 Python 的操作。 (由 Zackery Spytz 在 bpo-8901 中貢獻。)

  • 全局變量 PyStructSequence_UnnamedField 現在為常量并且指向一個(gè)字符串常量。 (由 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() 函數會(huì )被一個(gè)自動(dòng)記錄當前函數名稱(chēng)的宏所替代,除非已定義了 Py_LIMITED_API 宏。 (由 Victor Stinner 在 bpo-39882 中貢獻。)

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

  • 多個(gè)宏和函數的實(shí)現細節現在已被隱藏:

    (詳情請參閱 bpo-40170。)

移除?

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

  • PyTypeObjecttp_print 空位已被移除。 它在 Python 2.7 及之前的版本中被用來(lái)將對象打印到文件。 自 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 構建專(zhuān)屬)

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

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

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

    • PyAsyncGen_ClearFreeLists()

    • PyContext_ClearFreeList()

    • PyDict_ClearFreeList()

    • PyFloat_ClearFreeList()

    • PyFrame_ClearFreeList()

    • PyList_ClearFreeList()

    • PyMethod_ClearFreeList()PyCFunction_ClearFreeList(): 綁定方法對象的自由列表已被移除。

    • PySet_ClearFreeList(): 集合自由列表已在 Python 3.4 中被移除。

    • PyTuple_ClearFreeList()

    • PyUnicode_ClearFreeList(): Unicode 自由列表已在 Python 3.3 中被移除。

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

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

  • 清除了已定義但未實(shí)現的接口的頭文件。 被移除了公共 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 所描述的靜態(tài)類(lèi)型檢查器的行為。

  1. Literal 現在將是去重復的形參。

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

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

  4. 現在如果有任何一個(gè)參數不為 hashable,Literal 對象將在相等性比較期間引發(fā) TypeError。 請注意使用可變參數聲明 Literal 將不會(huì )拋出異常:

    >>>
    >>> 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 版來(lái)說(shuō),Python 現在完全支持在 macOS 11.0 (Big Sur) 和 Apple Silicon Macs (基于 ARM64 架構) 上構建和運行。 現在提供了一個(gè)新的通用構建類(lèi)型 universal2,用于在一組可執行文件上原生支持 ARM64Intel 64。 二進(jìn)制文件現在也可以在當前版本的 macOS 上編譯以部署到多種較舊的 macOS 版本上 (已測試 10.9),同時(shí)會(huì )基于運行時(shí)所使用的操作系統版本讓某些較新的 OS 功能和選項有條件地可用 ("弱鏈接") 。

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

Python 3.9.2 中的重要變化?

collections.abc?

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

urllib.parse?

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