Python 3.8 有什么新變化


Python 3.8 有什么新變化

轉 https://docs.python.org/zh-cn/3.8/whatsnew/3.8.html

編者

Raymond Hettinger

本文解釋了 Python 3.8 相比 3.7 的新增特性。 完整的詳情可參閱 更新日志

Python 3.8已於2019年10月14日發布。

摘要 - 發布重點

新的特性

賦值表達式

新增的語法 := 可在表達式內部為變量賦值。 它被昵稱為“海象運算符”因為它很像是 海象的眼睛和長牙

在這個示例中,賦值表達式可以避免調用 len() 兩次:

if (n := len(a)) > 10: print(f"List is too long ({n} elements, expected <= 10)") 

類似的益處還可出現在正則表達式匹配中需要使用兩次匹配對象的情況中,一次檢測用於匹配是否發生,另一次用於提取子分組:

discount = 0.0 if (mo := re.search(r'(\d+)% discount', advertisement)): discount = float(mo.group(1)) / 100.0 

此運算符也適用於配合 while 循環計算一個值來檢測循環是否終止,而同一個值又在循環體中再次被使用的情況:

# Loop over fixed length blocks
while (block := f.read(256)) != '': process(block) 

另一個值得介紹的用例出現於列表推導式中,在篩選條件中計算一個值,而同一個值又在表達式中需要被使用:

[clean_name.title() for name in names if (clean_name := normalize('NFC', name)) in allowed_names] 

請盡量將海象運算符的使用限制在清晰的場合中,以降低復雜性並提升可讀性。

請參閱 PEP 572 了解詳情。

(由 Morehouse 在 bpo-35224 中貢獻。)

僅限位置形參

新增了一個函數形參語法 / 用來指明某些函數形參必須使用僅限位置而非關鍵字參數的形式。 這種標記語法與通過 help() 所顯示的使用 Larry Hastings 的 Argument Clinic 工具標記的 C 函數相同。

在下面的例子中,形參 a 和 b 為僅限位置形參,c 或 d 可以是位置形參或關鍵字形參,而 e 或 f 要求為關鍵字形參:

def f(a, b, /, c, d, *, e, f): print(a, b, c, d, e, f) 

以下均為合法的調用:

f(10, 20, 30, d=40, e=50, f=60) 

但是,以下均為不合法的調用:

f(10, b=20, c=30, d=40, e=50, f=60) # b cannot be a keyword argument f(10, 20, 30, 40, 50, f=60) # e must be a keyword argument 

這種標記形式的一個用例是它允許純 Python 函數完整模擬現有的用 C 代碼編寫的函數的行為。 例如,內置的 pow() 函數不接受關鍵字參數:

def pow(x, y, z=None, /): "Emulate the built in pow() function" r = x ** y return r if z is None else r%z 

另一個用例是在不需要形參名稱時排除關鍵字參數。 例如,內置的 len() 函數的簽名為 len(obj, /)。 這可以排除如下這種笨拙的調用形式:

len(obj='hello') # The "obj" keyword argument impairs readability 

另一個益處是將形參標記為僅限位置形參將允許在未來修改形參名而不會破壞客戶的代碼。 例如,在 statistics 模塊中,形參名 dist 在未來可能被修改。 這使得以下函數描述成為可能:

def quantiles(dist, /, *, n=4, method='exclusive') ... 

由於在 / 左側的形參不會被公開為可用關鍵字,其他形參名仍可在 **kwargs 中使用:

>>>
>>> def f(a, b, /, **kwargs): ... print(a, b, kwargs) ... >>> f(10, 20, a=1, b=2, c=3) # a and b are used in two ways 10 20 {'a': 1, 'b': 2, 'c': 3} 

這極大地簡化了需要接受任意關鍵字參數的函數和方法的實現。 例如,以下是一段摘自 collections 模塊的代碼:

class Counter(dict): def __init__(self, iterable=None, /, **kwds): # Note "iterable" is a possible keyword argument 

請參閱 PEP 570 了解詳情。

(由 Pablo Galindo 在 bpo-36540 中貢獻。)

用於已編譯字節碼文件的並行文件系統緩存

新增的 PYTHONPYCACHEPREFIX 設置 (也可使用 -X pycache_prefix) 可將隱式的字節碼緩存配置為使用單獨的並行文件系統樹,而不是默認的每個源代碼目錄下的 __pycache__ 子目錄。

緩存的位置會在 sys.pycache_prefix 中報告 (None 表示默認位置即 __pycache__ 子目錄)。

(由 Carl Meyer 在 bpo-33499 中貢獻。)

調試構建使用與發布構建相同的 ABI

Python 現在不論是以發布模式還是調試模式進行構建都將使用相同的 ABI。 在 Unix 上,當 Python 以調試模式構建時,現在將可以加載以發布模式構建的 C 擴展和使用穩定版 ABI 構建的 C 擴展。

發布構建和調試構建現在都是 ABI 兼容的:定義 Py_DEBUG 宏不會再啟用 Py_TRACE_REFS 宏,它引入了唯一的 ABI 不兼容性。 Py_TRACE_REFS 宏添加了 sys.getobjects() 函數和 PYTHONDUMPREFS 環境變量,它可以使用新的 ./configure --with-trace-refs 構建選項來設置。 (由 Victor Stinner 在 bpo-36465 中貢獻。)

在 Unix 上,C 擴展不會再被鏈接到 libpython,但 Android 和 Cygwin 例外。 現在靜態鏈接的 Python 將可以加載使用共享庫 Python 構建的 C 擴展。 (由 Victor Stinner 在 bpo-21536 中貢獻。)

在 Unix 上,當 Python 以調試模式構建時,導入操作現在也會查找在發布模式下編譯的 C 擴展以及使用穩定版 ABI 編譯的 C 擴展。 (由 Victor Stinner 在 bpo-36722 中貢獻。)

要將 Python 嵌入到一個應用中,必須將新增的 --embed 選項傳給 python3-config --libs --embed 以獲得 -lpython3.8 (將應用鏈接到 libpython)。 要同時支持 3.8 和舊版本,請先嘗試 python3-config --libs --embed 並在此命令失敗時回退到 python3-config --libs (即不帶 --embed)。

增加一個 pkg-config python-3.8-embed 模塊用來將 Python 嵌入到一個應用中: pkg-config python-3.8-embed --libs 包含 -lpython3.8。 要同時支持 3.8 和舊版本,請先嘗試 pkg-config python-X.Y-embed --libs 並在此命令失敗時回退到 pkg-config python-X.Y --libs (即不帶 --embed) (請將 X.Y 替換為 Python 版本號)。

另一方面,pkg-config python3.8 --libs 不再包含 -lpython3.8。 C 擴展不可被鏈接到 libpython (但 Android 和 Cygwin 例外,這兩者的情況由腳本處理);此改變是故意被設為向下不兼容的。 (由 Victor Stinner 在 bpo-36721 中貢獻。)

f-字符串支持 = 用於自動記錄表達式和調試文檔

增加 = 說明符用於 f-string。 形式為 f'{expr=}' 的 f-字符串將擴展表示為表達式文本,加一個等於號,再加表達式的求值結果。 例如:

>>>
>>> user = 'eric_idle' >>> member_since = date(1975, 7, 31) >>> f'{user=} {member_since=}' "user='eric_idle' member_since=datetime.date(1975, 7, 31)" 

通常的 f-字符串格式說明符 允許更細致地控制所要顯示的表達式結果:

>>>
>>> delta = date.today() - member_since >>> f'{user=!s} {delta.days=:,d}' 'user=eric_idle delta.days=16,075' 

= 說明符將輸出整個表達式,以便詳細演示計算過程:

>>>
>>> print(f'{theta=} {cos(radians(theta))=:.3f}') theta=30 cos(radians(theta))=0.866 

(由 Eric V. Smith 和 Larry Hastings 在 bpo-36817 中貢獻。)

PEP 578: Python 運行時審核鈎子

此 PEP 添加了審核鈎子和已驗證開放鈎子。 兩者在 Python 與本機代碼中均可用。允許以純 Python 代碼編寫的應用和框架利用額外的通知,同時允許嵌入開發人員或系統管理員部署始終啟用審核的 Python 版本。

請參閱 PEP 578 了解詳情。

PEP 587: Python 初始化配置

PEP 587 增加了一個新的 C API 用來配置 Python 初始化,提供對整個配置過程的更細致控制以及更好的錯誤報告。

新的結構:

新的函數:

此 PEP 還為這些內部結構添加了 _PyRuntimeState.preconfig (PyPreConfig 類型) 和 PyInterpreterState.config (PyConfig 類型) 字段。 PyInterpreterState.config 成為新的引用配置,替代全局配置變量和其他私有變量。

請參閱 Python 初始化配置 獲取詳細文檔。

請參閱 PEP 587 了解詳情。

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

Vectorcall: 用於 CPython 的快速調用協議

添加 "vectorcall" 協議到 Python/C API。 它的目標是對已被應用於許多類的現有優化進行正式化。 任何實現可調用對象的擴展類型均可使用此協議。

此特性目前為暫定狀態,計划在 Python 3.9 將其完全公開。

請參閱 PEP 590 了解詳情。

(由 Jeroen Demeyer 和 Mark Shannon 在 bpo-36974 中貢獻。)

具有外部數據緩沖區的 pickle 協議 5

當使用 pickle 在 Python 進程間傳輸大量數據以充分發揮多核或多機處理的優勢時,非常重要一點是通過減少內存拷貝來優化傳輸效率,並可能應用一些定制技巧例如針對特定數據的壓縮。

pickle 協議 5 引入了對於外部緩沖區的支持,這樣 PEP 3118 兼容的數據可以與主 pickle 流分開進行傳輸,這是由通信層來確定的。

請參閱 PEP 574 了解詳情。

(由 Antoine Pitrou 在 bpo-36785 中貢獻。)

其他語言特性修改

  • 在之前版本中 continue 語句不允許在 finally 子句中使用,這是因為具體實現存在一個問題。 在 Python 3.8 中此限制已被取消。 (由 Serhiy Storchaka 在 bpo-32489 中貢獻。)

  • boolint 和 fractions.Fraction 類型現在都有一個 as_integer_ratio() 方法,與 float 和 decimal.Decimal 中的已有方法類似。 這個微小的 API 擴展使得 numerator, denominator x.as_integer_ratio() 這樣的寫法在多種數字類型上通用成為可能。 (由 Lisa Roach 在 bpo-33073 和 Raymond Hettinger 在 bpo-37819 中貢獻。)

  • intfloat 和 complex 的構造器現在會使用 __index__() 特殊方法,如果該方法可用而對應的方法 method __int__()__float__() 或 __complex__() 方法不可用的話。 (由 Serhiy Storchaka 在 bpo-20092 中貢獻。)

  • 添加 \N{name} 轉義符在 正則表達式 中的支持:

    >>>
    >>> notice = 'Copyright © 2019' >>> copyright_year_pattern = re.compile(r'\N{copyright sign}\s*(\d{4})') >>> int(copyright_year_pattern.search(notice).group(1)) 2019 

    (由 Jonathan Eunice 和 Serhiy Storchaka 在 bpo-30688 中貢獻。)

  • 現在 dict 和 dictview 可以使用 reversed() 按插入順序反向迭代。 (由 Rémi Lapeyre 在 bpo-33462 中貢獻。)

  • 在函數調用中允許使用的關鍵字名稱語法受到進一步的限制。 特別地,f((keyword)=arg) 不再被允許。 關鍵字參數賦值形式的左側絕不允許一般標識符以外的其他內容。 (由 Benjamin Peterson 在 bpo-34641 中貢獻。)

  • 在 yield 和 return 語句中的一般可迭代對象解包不再要求加圓括號。 這使得 yield 和 return 的語法與正常的賦值語法更為一致:

    >>>
    >>> def parse(family):  lastname, *members = family.split()  return lastname.upper(), *members >>> parse('simpsons homer marge bart lisa sally') ('SIMPSONS', 'homer', 'marge', 'bart', 'lisa', 'sally') 

    (由 David Cuthbert 和 Jordan Chapman 在 bpo-32117 中貢獻。)

  • 當類似 [(10, 20) (30, 40)] 這樣在代碼中少了一個逗號時,編譯器將顯示 SyntaxWarning 並附帶更有幫助的提示。 這相比原來用 TypeError 來提示第一個元組是不可調用的更容易被理解。 (由 Serhiy Storchaka 在 bpo-15248 中貢獻。)

  • datetime.date 或 datetime.datetime 和 datetime.timedelta 對象之間的算術運算現在將返回相應子類的實例而不是基類的實例。 這也會影響到在具體實現中(直接或間接地)使用了 datetime.timedelta 算術運算的返回類型,例如 astimezone()。 (由 Paul Ganssle 在 bpo-32417 中貢獻。)

  • 當 Python 解釋器通過 Ctrl-C (SIGINT) 被中斷並且所產生的 KeyboardInterrupt 異常未被捕獲,Python 進程現在會通過一個 SIGINT 信號或是使得發起調用的進程能檢測到它是由 Ctrl-C 操作殺死的正確退出代碼來退出。 POSIX 和 Windows 上的終端會相應地使用此代碼在交互式會話中終止腳本。 (由 Google 的 Gregory P. Smith 在 bpo-1054041 中貢獻。)

  • 某些高級編程風格要求為現有的函數更新 types.CodeType 對象。 由於代碼對象是不可變的,需要基於現有代碼對象模型創建一個新的代碼對象。 使用 19 個形參將會相當繁瑣。 現在,新的 replace() 方法使得通過少量修改的形參創建克隆對象成為可能。

    下面是一個修改 statistics.mean() 函數來防止 data 形參被用作關鍵字參數的例子:

    >>>
    >>> from statistics import mean >>> mean(data=[10, 20, 90]) 40 >>> mean.__code__ = mean.__code__.replace(co_posonlyargcount=1) >>> mean(data=[10, 20, 90]) Traceback (most recent call last): ... TypeError: mean() got some positional-only arguments passed as keyword arguments: 'data' 

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

  • 對於整數,現在 pow() 函數的三參數形式在底數與模數不可約的情況下允許指數為負值。 隨后它會在指數為 -1 時計算底數的模乘逆元,並對其他負指數計算反模的適當冪次。 例如,要計算 38 模 137 的 模乘逆元 則可寫為:

    >>>
    >>> pow(38, -1, 137) 119 >>> 119 * 38 % 137 1 

    模乘逆元在求解 線性丟番圖方程 會被用到。 例如,想要求出 4258𝑥 147𝑦 369 的整數解,首先應重寫為 4258𝑥 ≡ 369 (mod 147) 然后求解:

    >>>
    >>> x = 369 * pow(4258, -1, 147) % 147 >>> y = (4258 * x - 369) // -147 >>> 4258 * x + 147 * y 369 

    (由 Mark Dickinson 在 bpo-36027 中貢獻。)

  • 字典推導式已與字典字面值實現同步,會先計算鍵再計算值:

    >>>
    >>> # Dict comprehension >>> cast = {input('role? '): input('actor? ') for i in range(2)} role? King Arthur actor? Chapman role? Black Knight actor? Cleese >>> # Dict literal >>> cast = {input('role? '): input('actor? ')} role? Sir Robin actor? Eric Idle 

    對執行順序的保證對賦值表達式來說很有用,因為在鍵表達式中賦值的變量將可在值表達式中被使用:

    >>>
    >>> names = ['Martin von Löwis', 'Łukasz Langa', 'Walter Dörwald'] >>> {(n := normalize('NFC', name)).casefold() : n for name in names} {'martin von löwis': 'Martin von Löwis',  'łukasz langa': 'Łukasz Langa',  'walter dörwald': 'Walter Dörwald'} 

    (由 Jörn Heissler 在 bpo-35224 中貢獻。)

  • object.__reduce__() 方法現在可返回長度為二至六個元素的元組。 之前的上限為五個。 新增的第六個可選元素是簽名為 (obj, state) 的可調用對象。 這樣就允許直接控制特定對象的狀態更新。 如果元素值不為 None,該可調用對象將優先於對象的 __setstate__() 方法。 (由 Pierre Glaser 和 Olivier Grisel 在 bpo-35900 中貢獻。)

新增模塊

  • 新增的 importlib.metadata 模塊提供了從第三方包讀取元數據的(臨時)支持。 例如,它可以提取一個已安裝軟件包的版本號、入口點列表等等:

    >>>
    >>> # Note following example requires that the popular "requests" >>> # package has been installed. >>> >>> from importlib.metadata import version, requires, files >>> version('requests') '2.22.0' >>> list(requires('requests')) ['chardet (<3.1.0,>=3.0.2)'] >>> list(files('requests'))[:5] [PackagePath('requests-2.22.0.dist-info/INSTALLER'),  PackagePath('requests-2.22.0.dist-info/LICENSE'),  PackagePath('requests-2.22.0.dist-info/METADATA'),  PackagePath('requests-2.22.0.dist-info/RECORD'),  PackagePath('requests-2.22.0.dist-info/WHEEL')] 

    (由 Barry Warsaw 和 Jason R. Coombs 在 bpo-34632 中貢獻)。

改進的模塊

ast

AST 節點現在具有 end_lineno 和 end_col_offset 屬性,它們給出節點結束的精確位置。 (這只適用於具有 lineno 和 col_offset 屬性的節點。)

新增函數 ast.get_source_segment() 返回指定 AST 節點的源代碼。

(由 Ivan Levkivskyi 在 bpo-33416 中貢獻。)

ast.parse() 函數具有一些新的旗標:

  • type_comments=True 導致其返回與特定 AST 節點相關聯的 PEP 484 和 PEP 526 類型注釋文本;

  • mode='func_type' 可被用於解析 PEP 484 "簽名類型注釋" (為函數定義 AST 節點而返回);

  • feature_version=(3, N) 允許指定一個更早的 Python 3 版本。 例如,feature_version=(3, 4) 將把 async 和 await 視為非保留字。

(由 Guido van Rossum 在 bpo-35766 中貢獻。)

asyncio

asyncio.run() 已經從暫定狀態晉級為穩定 API。 此函數可被用於執行一個 coroutine 並返回結果,同時自動管理事件循環。 例如:

import asyncio async def main(): await asyncio.sleep(0) return 42 asyncio.run(main()) 

這 大致 等價於:

import asyncio async def main(): await asyncio.sleep(0) return 42 loop = asyncio.new_event_loop() asyncio.set_event_loop(loop) try: loop.run_until_complete(main()) finally: asyncio.set_event_loop(None) loop.close() 

The actual implementation is significantly more complex. Thus, asyncio.run() should be the preferred way of running asyncio programs.

(由 Yury Selivanov 在 bpo-32314 中貢獻。)

運行 python -m asyncio 將啟動一個原生異步 REPL。 這允許快速體驗具有最高層級 await 的代碼。 這時不再需要直接調用 asyncio.run(),因為此操作會在每次發起調用時產生一個新事件循環:

$ python -m asyncio
asyncio REPL 3.8.0
Use "await" directly instead of "asyncio.run()".
Type "help", "copyright", "credits" or "license" for more information.
>>> import asyncio
>>> await asyncio.sleep(10, result='hello')
hello

(由 Yury Selivanov 在 bpo-37028 中貢獻。)

The exception asyncio.CancelledError now inherits from BaseException rather than Exception. (Contributed by Yury Selivanov in bpo-32528.)

在 Windows 上,現在默認的事件循環為 ProactorEventLoop。 (由 Victor Stinner 在 bpo-34687 中貢獻。)

ProactorEventLoop 現在也支持 UDP。 (由 Adam Meily 和 Andrew Svetlov 在 bpo-29883 中貢獻。)

ProactorEventLoop 現在可通過 KeyboardInterrupt ("CTRL+C") 來中斷。 (由 Vladimir Matveev 在 bpo-23057 中貢獻。)

Added asyncio.Task.get_coro() for getting the wrapped coroutine within an asyncio.Task. (Contributed by Alex Grönholm in bpo-36999.)

Asyncio tasks can now be named, either by passing the name keyword argument to asyncio.create_task() or the create_task() event loop method, or by calling the set_name() method on the task object. The task name is visible in the repr() output of asyncio.Task and can also be retrieved using the get_name() method. (Contributed by Alex Grönholm in bpo-34270.)

Added support for Happy Eyeballs to asyncio.loop.create_connection(). To specify the behavior, two new parameters have been added: happy_eyeballs_delay and interleave. The Happy Eyeballs algorithm improves responsiveness in applications that support IPv4 and IPv6 by attempting to simultaneously connect using both. (Contributed by twisteroid ambassador in bpo-33530.)

builtins

內置的 compile() 已改進為可接受 ast.PyCF_ALLOW_TOP_LEVEL_AWAIT 旗標。 當傳入此新旗標時,compile() 將允許通常被視為無效語法的最高層級 awaitasync for 和 async with 構造。 此后將可返回帶有 CO_COROUTINE 旗標的異步代碼對象。 (由 Matthias Bussonnier 在 bpo-34616 中貢獻。)

collections

collections.namedtuple() 的 _asdict() 方法現在將返回 dict 而不是 collections.OrderedDict。 此項更改是由於普通字典自 Python 3.7 起已保證具有確定的元素順序。 如果還需要 OrderedDict 的額外特性,建議的解決方案是將結果轉換為需要的類型: OrderedDict(nt._asdict())。 (由 Raymond Hettinger 在 bpo-35864 中貢獻。)

cProfile

cProfile.Profile 類現在可被用作上下文管理器。 在運行時對一個代碼塊實現性能分析:

import cProfile with cProfile.Profile() as profiler: # code to be profiled ... 

(由 Scott Sanderson 在 bpo-29235 中貢獻。)

csv

The csv.DictReader now returns instances of dict instead of a collections.OrderedDict. The tool is now faster and uses less memory while still preserving the field order. (Contributed by Michael Selik in bpo-34003.)

curses

添加了一個新變量用於保存下層 ncurses 庫的結構版信息: ncurses_version。 (由 Serhiy Storchaka 在 bpo-31680 中貢獻。)

ctypes

在 Windows 上,CDLL 及其子類現在接受 winmode 形參來指定用於底層 LoadLibraryEx 調用的旗標。 默認旗標被設為僅加載來自可信任位置的 DLL 依賴項,包括 DLL 的存放路徑(如果加載初始 DLL 時使用了完整或部分路徑)以及通過 add_dll_directory() 添加的路徑。 (由 Steve Dower 在 bpo-36085 中貢獻。)

datetime

添加了新的替代構造器 datetime.date.fromisocalendar() 和 datetime.datetime.fromisocalendar(),它們分別基於 ISO 年份、周序號和周內日序號來構造 date 和 datetime 對象;這兩者分別是其所對應類中 isocalendar 方法的逆操作。 (由 Paul Ganssle 在 bpo-36004 中貢獻。)

functools

functools.lru_cache() 現在可直接作為裝飾器而不是作為返回裝飾器的函數。 因此這兩種寫法現在都被支持:

@lru_cache
def f(x): ... @lru_cache(maxsize=256) def f(x): ... 

(由 Raymond Hettinger 在 bpo-36772 中貢獻。)

添加了新的 functools.cached_property() 裝飾器,用於在實例生命周期內緩存的已計算特征屬性。

import functools import statistics class Dataset: def __init__(self, sequence_of_numbers): self.data = sequence_of_numbers @functools.cached_property def variance(self): return statistics.variance(self.data) 

(由 Carl Meyer 在 bpo-21145 中貢獻)

添加了新的 functools.singledispatchmethod() 裝飾器可使用 single dispatch 將方法轉換為 泛型函數:

from functools import singledispatchmethod from contextlib import suppress class TaskManager: def __init__(self, tasks): self.tasks = list(tasks) @singledispatchmethod def discard(self, value): with suppress(ValueError): self.tasks.remove(value) @discard.register(list) def _(self, tasks): targets = set(tasks) self.tasks = [x for x in self.tasks if x not in targets] 

(由 Ethan Smith 在 bpo-32380 中貢獻)

gc

get_objects() 現在能接受一個可選的 generation 形參來指定一個用於獲取對象的生成器。 (由 Pablo Galindo 在 bpo-36016 中貢獻。)

gettext

添加了 pgettext() 及其變化形式。 (由 Franz Glasner, Éric Araujo 和 Cheryl Sabella 在 bpo-2504 中貢獻。)

gzip

添加 mtime 形參到 gzip.compress() 用於可重現的輸出。 (由 Guo Ci Teo 在 bpo-34898 中貢獻。)

對於特定類型的無效或已損壞 gzip 文件現在將引發 BadGzipFile 而不是 OSError。 (由 Filip Gruszczyński, Michele Orrù 和 Zackery Spytz 在 bpo-6584 中貢獻。)

IDLE 與 idlelib

超過 N 行(默認值為 50)的輸出將被折疊為一個按鈕。 N 可以在 Settings 對話框的 General 頁的 PyShell 部分中進行修改。 數量較少但是超長的行可以通過在輸出上右擊來折疊。 被折疊的輸出可通過雙擊按鈕來展開,或是通過右擊按鈕來放入剪貼板或是單獨的窗口。 (由 Tal Einat 在 bpo-1529353 中貢獻。)

在 Run 菜單中增加了 "Run Customized" 以使用自定義設置來運行模塊。 輸入的任何命令行參數都會被加入 sys.argv。 它們在下次自定義運行時會再次顯示在窗體中。 用戶也可以禁用通常的 Shell 主模塊重啟。 (由 Cheryl Sabella, Terry Jan Reedy 等人在 bpo-5680 和 bpo-37627 中貢獻。)

在 IDLE 編輯器窗口中增加了可選的行號。 窗口打開時默認不顯示行號,除非在配置對話框的 General 選項卡中特別設置。 已打開窗口中的行號可以在 Options 菜單中顯示和隱藏。 (由 Tal Einat 和 Saimadhav Heblikar 在 bpo-17535 中貢獻。)

現在會使用 OS 本機編碼格式在 Python 字符串和 Tcl 對象間進行轉換。 這允許在 IDLE 中處理 emoji 和其他非 BMP 字符。 這些字符將可被顯示或是從剪貼板復制和粘貼。 字符串從 Tcl 到 Python 的來回轉換現在不會再發生失敗。 (過去八年有許多人都為此付出過努力,問題最終由 Serhiy Storchaka 在 bpo-13153 中解決。)

上述修改已被反向移植到 3.7 維護發行版中。

inspect

inspect.getdoc() 函數現在可以找到 __slots__ 的文檔字符串,如果該屬性是一個元素值為文檔字符串的 dict 的話。 這提供了類似於目前已有的 property()classmethod() 和 staticmethod() 等函數的文檔選項:

class AudioClip: __slots__ = {'bit_rate': 'expressed in kilohertz to one decimal place', 'duration': 'in seconds, rounded up to an integer'} def __init__(self, bit_rate, duration): self.bit_rate = round(bit_rate / 1000.0, 1) self.duration = ceil(duration) 

(由 Raymond Hettinger 在 bpo-36326 中貢獻。)

io

在開發模式 (-X env) 和調試構建中,io.IOBase 終結器現在會在 close() 方法失敗時將異常寫入日志。 發生的異常在發布構建中默認會被靜默忽略。 (由 Victor Stinner 在 bpo-18748 中貢獻。)

itertools

itertools.accumulate() 函數增加了可選的 initial 關鍵字參數用來指定一個初始值:

>>>
>>> from itertools import accumulate >>> list(accumulate([10, 5, 30, 15], initial=1000)) [1000, 1010, 1015, 1045, 1060] 

(由 Lisa Roach 在 bpo-34659 中貢獻。)

json.tool

添加選項 --json-lines 用於將每個輸入行解析為單獨的 JSON 對象。 (由 Weipeng Hong 在 bpo-31553 中貢獻。)

logging

Added a force keyword argument to logging.basicConfig() When set to true, any existing handlers attached to the root logger are removed and closed before carrying out the configuration specified by the other arguments.

這解決了一個長期存在的問題。 當一個日志處理器或 basicConfig() 被調用時,對 basicConfig() 的后續調用會被靜默地忽略。 這導致使用交互提示符或 Jupyter 筆記本更新、試驗或講解各種日志配置選項變得相當困難。

(由 Raymond Hettinger 提議,由 Dong-hee Na 實現,並由 Vinay Sajip 在 bpo-33897 中完成審核。)

math

添加了新的函數 math.dist() 用於計算兩點之間的歐幾里得距離。 (由 Raymond Hettinger 在 bpo-33089 中貢獻。)

擴展了 math.hypot() 函數以便處理更多的維度。 之前它僅支持 2-D 的情況。 (由 Raymond Hettinger 在 bpo-33089 中貢獻。)

添加了新的函數 math.prod() 作為的 sum() 同類,該函數返回 'start' 值 (默認值: 1) 乘以一個數字可迭代對象的積:

>>>
>>> prior = 0.8 >>> likelihoods = [0.625, 0.84, 0.30] >>> math.prod(likelihoods, start=prior) 0.126 

(由 Pablo Galindo 在 bpo-35606 中貢獻。)

添加了兩個新的組合函數 math.perm() 和 math.comb():

>>>
>>> math.perm(10, 3) # Permutations of 10 things taken 3 at a time 720 >>> math.comb(10, 3) # Combinations of 10 things taken 3 at a time 120 

(由 Yash Aggarwal, Keller Fuchs, Serhiy Storchaka 和 Raymond Hettinger 在 bpo-37128bpo-37178 和 bpo-35431 中貢獻。)

添加了一個新函數 math.isqrt() 用於計算精確整數平方根而無需轉換為浮點數。 該新函數支持任意大整數。 它的執行速度比 floor(sqrt(n)) 快但是比 math.sqrt() 慢:

>>>
>>> r = 650320427 >>> s = r ** 2 >>> isqrt(s - 1) # correct 650320426 >>> floor(sqrt(s - 1)) # incorrect 650320427 

(由 Mark Dickinson 在 bpo-36887 中貢獻。)

函數 math.factorial() 不再接受非整數類參數。 (由 Pablo Galindo 在 bpo-33083 中貢獻。)

mmap

mmap.mmap 類現在具有一個 madvise() 方法用於訪問 madvise() 系統調用。 (由 Zackery Spytz 在 bpo-32941 中貢獻。)

multiprocessing

添加了新的 multiprocessing.shared_memory 模塊。 (由 Davin Potts 在 bpo-35813 中貢獻。)

在macOS上,現在默認使用的啟動方式是*spawn*啟動方式。 (由 Victor Stinner 在 bpo-33725 中貢獻。)

os

在 Windows 上添加了新函數 add_dll_directory() 用於在導入擴展模塊或使用 ctypes 加載 DLL 時為本機依賴提供額外搜索路徑 。 (由 Steve Dower 在 bpo-36085 中貢獻。)

添加了新的 os.memfd_create() 函數用於包裝 memfd_create() 系統調用。 (由 Zackery Spytz 和 Christian Heimes 在 bpo-26836 中貢獻。)

在 Windows 上,大部分用於處理重解析點,(包括符號鏈接和目錄連接)的手動邏輯已被委托給操作系統。 特別地,os.stat() 現在將會遍歷操作系統所支持的任何內容,而 os.lstat() 將只打開被標識為“名稱代理”的重解析點,而其要由 os.stat() 打開其他的重解析點。 在所有情況下,stat_result.st_mode 將只為符號鏈接而非其他種類的重解析點設置 S_IFLNK。 要標識其他種類的重解析點,請檢查新的 stat_result.st_reparse_tag 屬性。

在 Windows 上,os.readlink() 現在能夠讀取目錄連接。 請注意 islink() 會對目錄連接返回 False,因此首先檢查 islink 的代碼將連續把連接視為目錄,而會處理 os.readlink() 所引發錯誤的代碼現在會把連接視為鏈接。

(由 Steve Dower 在 bpo-37834 中貢獻。)

os.path

返回布爾值結果的 os.path 函數例如 exists()lexists()isdir()isfile()islink(), 以及 ismount() 現在對於包含在 OS 層級無法表示的字符或字節的路徑將會返回 False 而不是引發 ValueError 或其子類 UnicodeEncodeError 和 UnicodeDecodeError。 (由 Serhiy Storchaka 在 bpo-33721 中貢獻。)

expanduser() 在 Windows 上現在改用 USERPROFILE 環境變量而不再使用 HOME,后者通常不會為一般用戶賬戶設置。 (由 Anthony Sottile 在 bpo-36264 中貢獻。)

isdir() on Windows no longer returns True for a link to a non-existent directory.

realpath() 在 Windows 上現在會識別重解析點,包括符號鏈接和目錄連接。

(由 Steve Dower 在 bpo-37834 中貢獻。)

pathlib

返回布爾值結果的 pathlib.Path 方法例如 exists()is_dir()is_file()is_mount()is_symlink()is_block_device()is_char_device()is_fifo()is_socket() 現在對於包含在 OS 層級無法表示的字符或字節的路徑將會返回 False 而不是引發 ValueError 或其子類 UnicodeEncodeError。 (由 Serhiy Storchaka 在 bpo-33721 中貢獻。)

添加了 pathlib.Path.link_to() 用於創建指向某個路徑的硬鏈接。 (由 Joannah Nanjekye 在 bpo-26978 中貢獻。)

pickle

pickle 擴展子類化針對 C 優化的 Pickler 現在可通過定義特殊的 reducer_override() 方法來重載函數和類的封存邏輯。 (由 Pierre Glaser 和 Olivier Grisel 在 bpo-35900 中貢獻。)

plistlib

添加了新的 plistlib.UID 並啟動了對讀取和寫入經過 NSKeyedArchiver 編碼的二進制 plists 的支持。 (由 Jon Janzen 在 bpo-26707 中貢獻。)

pprint

The pprint module added a sort_dicts parameter to several functions. By default, those functions continue to sort dictionaries before rendering or printing. However, if sort_dicts is set to false, the dictionaries retain the order that keys were inserted. This can be useful for comparison to JSON inputs during debugging.

In addition, there is a convenience new function, pprint.pp() that is like pprint.pprint() but with sort_dicts defaulting to False:

>>>
>>> from pprint import pprint, pp >>> d = dict(source='input.txt', operation='filter', destination='output.txt') >>> pp(d, width=40) # Original order {'source': 'input.txt',  'operation': 'filter',  'destination': 'output.txt'} >>> pprint(d, width=40) # Keys sorted alphabetically {'destination': 'output.txt',  'operation': 'filter',  'source': 'input.txt'} 

(由 Rémi Lapeyre 在 bpo-30670 中貢獻。)

py_compile

py_compile.compile() 現在支持靜默模式。 (由 Joannah Nanjekye 在 bpo-22640 中貢獻。)

shlex

新增了 shlex.join() 函數作為 shlex.split() 的逆操作。 (由 Bo Bayles 在 bpo-32102 中貢獻。)

shutil

shutil.copytree() 現在接受新的 dirs_exist_ok 關鍵字參數。 (由 Josh Bronson 在 bpo-20849 中貢獻。)

shutil.make_archive() 現在對新的歸檔默認使用 modern pax (POSIX.1-2001) 格式以提升可移植性和標准一致性,此特性繼承自對 tarfile 模塊的相應更改。 (由 C.A.M. Gerlach 在 bpo-30661 中貢獻。)

shutil.rmtree() 在 Windows 上現在會移除目錄連接而不會遞歸地先移除其中的內容。 (由 Steve Dower 在 bpo-37834 中貢獻。)

socket

添加了便捷的 create_server() 和 has_dualstack_ipv6() 函數以自動化在創建服務器套接字時通常情況下所必須的任務,包括在同一套接字中同時接受 IPv4 和 IPv6 連接。 (由 Giampaolo Rodolà 在 bpo-17561 中貢獻。)

socket.if_nameindex()socket.if_nametoindex() 和 socket.if_indextoname() 函數已經在 Windows 上實現。 (由 Zackery Spytz 在 bpo-37007 中貢獻。)

ssl

增加了 post_handshake_auth 和 verify_client_post_handshake() 分別啟用和初始化 TLS 1.3 握手后驗證。 (由 Christian Heimes 在 bpo-34670 中貢獻。)

statistics

添加了 statistics.fmean() 作為 statistics.mean() 的更快速的浮點數版版本。 (由 Raymond Hettinger 和 Steven D'Aprano 在 bpo-35904 中貢獻。)

添加了 statistics.geometric_mean() (由 Raymond Hettinger 在 bpo-27181 中貢獻。)

添加了 statistics.multimode() 用於返回最常見值的列表。 (由 Raymond Hettinger 在 bpo-35892 中貢獻。)

添加了 statistics.quantiles() 用於將數據或分布划分為多個等概率區間(例如四分位、十分位或百分位)。 (由 Raymond Hettinger 在 bpo-36546 中貢獻。)

添加了 statistics.NormalDist 用於創建和操縱隨機變量的正態分布。 (由 Raymond Hettinger 在 bpo-36018 中貢獻。)

>>>
>>> temperature_feb = NormalDist.from_samples([4, 12, -3, 2, 7, 14]) >>> temperature_feb.mean 6.0 >>> temperature_feb.stdev 6.356099432828281 >>> temperature_feb.cdf(3) # Chance of being under 3 degrees 0.3184678262814532 >>> # Relative chance of being 7 degrees versus 10 degrees >>> temperature_feb.pdf(7) / temperature_feb.pdf(10) 1.2039930378537762 >>> el_niño = NormalDist(4, 2.5) >>> temperature_feb += el_niño # Add in a climate effect >>> temperature_feb NormalDist(mu=10.0, sigma=6.830080526611674) >>> temperature_feb * (9/5) + 32 # Convert to Fahrenheit NormalDist(mu=50.0, sigma=12.294144947901014) >>> temperature_feb.samples(3) # Generate random samples [7.672102882379219, 12.000027119750287, 4.647488369766392] 

sys

添加了新的 sys.unraisablehook() 函數,可被重載以便控制如何處理“不可引發的異常”。 它會在發生了一個異常但 Python 沒有辦法處理時被調用。 例如,當一個析構器在垃圾回收時 (gc.collect()) 所引發的異常。 (由 Victor Stinner 在 bpo-36829 中貢獻。)

tarfile

tarfile 模塊現在對新的歸檔默認使用 modern pax (POSIX.1-2001) 格式而不再是之前的 GNU 專屬格式。 這通過標准化和可擴展格式的統一編碼 (UTF-8) 提升了跨平台可移植性,還提供了其他一些益處。 (由 C.A.M. Gerlach 在 bpo-36268 中貢獻。)

threading

添加了新的 threading.excepthook() 函數用來處理未捕獲的 threading.Thread.run() 異常。 它可被重載以便控制如何處理未捕獲的 threading.Thread.run() 異常。 (由 Victor Stinner 在 bpo-1230540 中貢獻。)

添加了新的 threading.get_native_id() 函數以及 threading.Thread 類的 native_id 屬性。 它們會返回內核所分配給當前線程的原生整數線程 ID。 此特性僅在特定平台上可用,參見 get_native_id 了解詳情。 (由 Jake Tesler 在 bpo-36084 中貢獻。)

tokenize

當提供不帶末尾新行的輸入時,tokenize 模塊現在會隱式地添加 NEWLINE 形符。 此行為現在已與 C 詞法分析器的內部行為相匹配。 (由 Ammar Askar 在 bpo-33899 中貢獻。)

tkinter

在 tkinter.Spinbox 中添加了方法 selection_from()selection_present()selection_range() 和 selection_to()。 (由 Juliette Monsel 在 bpo-34829 中貢獻。)

在 tkinter.Canvas 類中添加了方法 moveto()。 (由 Juliette Monsel 在 bpo-23831 中貢獻。)

tkinter.PhotoImage 類現在具有 transparency_get() 和 transparency_set() 方法。 (由 Zackery Spytz 在 bpo-25451 中貢獻。)

time

為 macOS 10.12 添加了新的時鍾 CLOCK_UPTIME_RAW。 (由 Joannah Nanjekye 在 bpo-35702 中貢獻。)

typing

typing 模塊加入了一些新特性:

  • 一個帶有鍵專屬類型的字典類型。 參見 PEP 589 和 typing.TypedDict。 TypedDict 只使用字符串作為鍵。 默認情況下每個鍵都要求提供。 指定 "total=False" 以允許鍵作為可選項:

    class Location(TypedDict, total=False): lat_long: tuple grid_square: str xy_coordinate: tuple 
  • Literal 類型。 參見 PEP 586 和 typing.Literal。 Literal 類型指明一個形參或返回值被限定為一個或多個特定的字面值:

    def get_status(port: int) -> Literal['connected', 'disconnected']: ... 
  • "Final" 變量、函數、方法和類。 參見 PEP 591typing.Final 和 typing.final()。 final 限定符會指示靜態類型檢查器限制進行子類化、重載或重新賦值:

    pi: Final[float] = 3.1415926536 
  • 協議定義。 參見 PEP 544typing.Protocol 和 typing.runtime_checkable()。 簡單的 ABC 例如 typing.SupportsInt 現在是 Protocol 的子類。

  • 新的協議類 typing.SupportsIndex

  • 新的函數 typing.get_origin() 和 typing.get_args()

unicodedata

unicodedata 模塊現在已升級為使用 Unicode 12.1.0 發布版。

新的函數 is_normalized() 可被用來驗證字符串是否為特定正規形式,通常會比實際進行字符串正規化要快得多。 (由 Max Belanger, David Euresti 和 Greg Price 在 bpo-32285 和 bpo-37966 中貢獻。)

unittest

添加了 AsyncMock 以支持異步版本的 Mock。 同時也添加了相應的斷言函數用於測試。 (由 Lisa Roach 在 bpo-26467 中貢獻。)

unittest 添加了 addModuleCleanup() 和 addClassCleanup() 以支持對 setUpModule() 和 setUpClass() 進行清理。 (由 Lisa Roach 在 bpo-24412 中貢獻。)

一些模擬斷言函數現在也會在失敗時打印一個實際調用列表。 (由 Petter Strandmark 在 bpo-35047 中貢獻。)

unittest 模塊已支持通過 unittest.IsolatedAsyncioTestCase 來使用協程作為測試用例。 (由 Andrew Svetlov 在 bpo-32972 中貢獻。)

示例:

import unittest class TestRequest(unittest.IsolatedAsyncioTestCase): async def asyncSetUp(self): self.connection = await AsyncConnection() async def test_get(self): response = await self.connection.get("https://example.com") self.assertEqual(response.status_code, 200) async def asyncTearDown(self): await self.connection.close() if __name__ == "__main__": unittest.main() 

venv

現在 venv 在所有平台上都會包含 Activate.ps1 腳本用於在 PowerShell Core 6.1 下激活虛擬環境。 (由 Brett Cannon 在 bpo-32718 中貢獻。)

weakref

由 weakref.proxy() 返回的代理對象現在除其他算術運算符外也支持矩陣乘法運算符 @ 和 @=。 (由 Mark Dickinson 在 bpo-36669 中貢獻。)

xml

作為對 DTD 和外部實體檢索的緩解,在默認情況下 xml.dom.minidom 和 xml.sax 模塊不再處理外部實體。 (由 Christian Heimes 在 bpo-17239 中貢獻。)

xml.etree.ElementTree 模塊中的 .find*() 方法支持通配符搜索例如 {*}tag,此搜索會忽略命名空間以及返回給定命名空間中所有標簽的 {namespace}*。 (由 Stefan Behnel 在 bpo-28238 中貢獻。)

xml.etree.ElementTree 模塊提供了實現 C14N 2.0 的新函數 –xml.etree.ElementTree.canonicalize()。 (由 Stefan Behnel 在 bpo-13611 中貢獻。)

xml.etree.ElementTree.XMLParser 的目標對象可通過新的回調方法 start_ns() 和 end_ns() 來接受命名空間聲明事件。 此外,xml.etree.ElementTree.TreeBuilder 目標可被配置為處理有關注釋和處理指令事件以將它們包含在所生成的樹當中。 (由 Stefan Behnel 在 bpo-36676 和 bpo-36673 中貢獻。)

xmlrpc

xmlrpc.client.ServerProxy 現在支持可選的 headers 關鍵字參數作為隨同每次請求發送的 HTTP 標頭序列。 此特征的作用之一是使得從默認的基礎認證升級到更快速的會話認證成為可能。 (由 Cédric Krier 在 bpo-35153 中貢獻。)

性能優化

  • subprocess 模塊現在能在某些情況下使用 os.posix_spawn() 函數以獲得更好的性能。 目前,它的使用僅限 macOS 和 Linux(使用 glibc 2.24 或更新版本),並要求滿足以下條件:

    • close_fds 為假值;

    • preexec_fnpass_fdscwd 和 start_new_session 形參未設置;

    • executable 路徑包含一個目錄。

    (由 Joannah Nanjekye 和 Victor Stinner 在 bpo-35537 中貢獻。)

  • shutil.copyfile()shutil.copy()shutil.copy2()shutil.copytree() 和 shutil.move() 在 Linux 和 macOS 上會使用平台專屬的 "fast-copy" 系統調用以提高效率。 "fast-copy" 意味着拷貝操作發生於內核中,從而避免在進行 "outfd.write(infd.read())" 等操作時使用 Python 中的用戶空間緩沖區。 在 Windows 上 shutil.copyfile() 會使用更大的默認緩沖區(1 MiB 而不是 16 KiB)並且使用基於 memoryview() 的 shutil.copyfileobj() 版本。 在同一分區內拷貝一個 512 MiB 文件的速度提升在 Linux 上約為 +26%,在 macOS 上為 +50%,在 Windows 上為 +40%。 此外還將消耗更少的 CPU 周期。 參見 依賴於具體平台的高效拷貝操作 一節。 (由 Giampaolo Rodolà 在 bpo-33671 中貢獻。)

  • shutil.copytree() 會根據其所用緩存的 os.stat() 值使用 os.scandir() 函數及所有拷貝函數。 拷貝一個包含 8000 文件的目錄的速度提升在 Linux 上約為 +9%,在 Windows 上為 +20%,對於 Windows SMB 共享目錄則為 +30%。 此外 os.stat() 系統調用的次數也減少了 38%,使得 shutil.copytree() 在網絡文件系統上會特別快速。 (由Giampaolo Rodolà 在 bpo-33695 中貢獻。)

  • pickle 模塊使用的默認協議現在為 Protocol 4,最早在 Python 3.4 中被引入。 它提供了比自 Python 3.0 起可用的 Protocol 3 更好的性能和更小的數據尺寸。

  • 從 PyGC_Head 移除了一個 Py_ssize_t 成員。 所有跟蹤 GC 的對象(例如 tuple, list, dict)大小減少了 4 或 8 字節。 (由 Inada Naoki 在 bpo-33597 中貢獻。)

  • uuid.UUID 現在會使用 __slots__ 以減少內存足跡。 (由 Wouter Bolsterlee 和 Tal Einat 在 bpo-30977 中貢獻。)

  • operator.itemgetter() 的性能提升了 33%。 優化了參數處理,並為常見的在元組中單個非負整數索引的情況新增了一條快速路徑(這是標准庫中的典型用例)。 (由 Raymond Hettinger 在 bpo-35664 中貢獻。

  • 加快了在 collections.namedtuple() 中的字段查找。 它們現在的速度快了兩倍以上,成為 Python 中最快的實例變量查找形式。 (由 Raymond Hettinger, Pablo Galindo 和 Joe Jevnik, Serhiy Storchaka 在 bpo-32492 中貢獻。)

  • 如果輸入的可迭代對象的長度已知 (即輸入對象實現了 __len__),list 構造器不會過度分配內部項緩沖區。 這使得所創建的列表資源占用平均減少了 12%。 (由 Raymond Hettinger 和 Pablo Galindo 在 bpo-33234 中貢獻。)

  • 類變量寫入速度加倍。 當一個非冗余屬性被更新時,之前存在一個更新 slots 的非必要調用。 (由 Stefan Behnel, Pablo Galindo Salgado, Raymond Hettinger, Neil Schemenauer, 和 Serhiy Storchaka 在 bpo-36012 中貢獻。)

  • 減少了傳遞給許多內置函數和方法的參數轉換的開銷。 這使得某些簡單內置函數和方法的速度提升了 20--50%。 (由 Serhiy Storchaka 在 bpo-23867bpo-35582 和 bpo-36127 中貢獻。)

  • LOAD_GLOBAL 指令現在會使用新的 "per opcode cache" 機制。 它的速度現在提升了大約 40%。 (由 Yury Selivanov 和 Inada Naoki 在 bpo-26219 中貢獻。)

構建和 C API 的改變

  • 默認的 sys.abiflags 成為一個空字符串:pymalloc 的 m 旗標不再有意義(無論是否啟用 pymalloc 構建都是兼容 ABI 的)因此已被移除。 (由 Victor Stinner 在 bpo-36707 中貢獻。)

    改變的例子:

    • 只會安裝 python3.8 程序,不再有 python3.8m 程序。

    • 只會安裝 python3.8-config 腳本,不再有 python3.8m-config 腳本。

    • m 旗標已經從動態庫文件名后綴中移除:包括標准庫中的擴展模塊以及第三方包所產生和安裝的模塊例如從 PyPI 下載的模塊。 以 Linux 為例,Python 3.7 的后綴 .cpython-37m-x86_64-linux-gnu.so 在 Python 3.8 中改為 .cpython-38-x86_64-linux-gnu.so

  • 重新組織了所有頭文件以更好地區分不同種類的 API:

    • Include/*.h 應為可移植的公有穩定版 C API。

    • Include/cpython/*.h 應為 CPython 專屬的不穩定版 C API;公有 API,部分私有 API 附加 _Py or _PY 前綴。

    • Include/internal/*.h 應為 CPython 特別專屬的私有內部 C API。 此 API 不具備向下兼容保證並且不應在 CPython 以外被使用。 它們的公開僅適用於特別限定的需求例如調試器和性能分析等必須直接訪問 CPython 內部數據而不通過調用函數的應用。 此 API 現在是通過 make install 安裝的。

    (由 Victor Stinner 在 bpo-35134 和 bpo-35081 中貢獻,相關工作由 Eric Snow 在 Python 3.7 中發起。)

  • 某些宏已被轉換為靜態內聯函數:形參類型和返回類型定義良好,它們不再會有與宏相關的問題,變量具有局部作用域。 例如:

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

  • PyByteArray_Init() 和 PyByteArray_Fini() 函數已被移除。 它們自 Python 2.7.4 和 Python 3.2.0 起就沒有任何用處,被排除在受限 API (穩定版 ABI) 之外,並且未被寫入文檔。 (由 Victor Stinner 在 bpo-35713 中貢獻。)

  • PyExceptionClass_Name() 的結果類型現在是 const char * 而非 char *。 (由 Serhiy Storchaka 在 bpo-33818 中貢獻。)

  • Modules/Setup.dist 與 Modules/Setup 兩者的共存已被移除。 之前在更新 CPython 源碼樹時,開發者必須手動拷貝 Modules/Setup.dist (在源碼樹內) 到 Modules/Setup (在構建樹內) 以反映上游的任何改變。 舊特性對打包者來說有一點益處,但代價是對追蹤 CPython 開發進程的開發者造成經常性的麻煩,因為忘記拷貝該文件可能導致構建失敗。

    現在構建系統總是會從源碼樹內的 Modules/Setup 讀取數據。 建議希望定制該文件的開發者在 CPython 的一個 git 分叉或補丁文件中維護他們的更改,就如他們對源碼樹做任何其他改變時一樣。

    (由 Antoine Pitrou 在 bpo-32430 中貢獻。)

  • 將 Python 數字轉換為 C 整型的函數例如 PyLong_AsLong() 以及帶有 'i' 之類整型轉換格式單元的參數解析函數例如 PyArg_ParseTuple() 現在如果可能將會使用 __index__() 特殊方法而不是 __int__()。 對於帶有 __int__() 方法但沒有 __index__() 方法的對象 (例如 Decimal 和 Fraction) 將會發出棄用警告。 對於實現了 __index__() 的對象 PyNumber_Check() 現在將返回 1。 PyNumber_Long()PyNumber_Float() 和 PyFloat_AsDouble() 現在如果可能也將會使用 __index__() 方法。 (由 Serhiy Storchaka 在 bpo-36048 和 bpo-20092 中貢獻。)

  • 堆分配類型對象現在將增加它們在 PyObject_Init() (及其對應的宏 PyObject_INIT) 中的引用計數而不是在 PyType_GenericAlloc() 中。 修改實例分配或中止分配的類型可能需要進行調整。 (由 Elizondo 在 bpo-35810 中貢獻。)

  • 新增函數 PyCode_NewWithPosOnlyArgs() 允許創建代碼對象例如 PyCode_New(),但帶有一個額外的 posonlyargcount 形參以指明僅限位置參數的數量。 (由 Pablo Galindo 在 bpo-37221 中貢獻。)

  • Py_SetPath() 現在會將 sys.executable 設為程序完整路徑 (Py_GetProgramFullPath()) 而不是程序名稱 (Py_GetProgramName())。 (由 Victor Stinner 在 bpo-38234 中貢獻。)

棄用

API 與特性的移除

下列特性與 API 已從 Python 3.8 中移除:

  • 自 Python 3.3 起,從 collections 導入 ABC 的做法已棄用,而應當從 collections.abc 執行導入。 從 collections 導入的操作在 3.8 中已標記為被移除,但將推遲到 3.9 中實施。 (參見 bpo-36952。)

  • macpath 模塊,在 Python 3.7 中棄用,現已被移除。 (由 Victor Stinner 在 bpo-35471 中貢獻。)

  • 函數 platform.popen() 已被移除,它自 Python 3.3 起就已被棄用:請改用 os.popen()。 (由 Victor Stinner 在 bpo-35345 中貢獻。)

  • 函數 time.clock() 已被移除,它自 Python 3.3 起就已被棄用:請根據具體需求改用 time.perf_counter() 或 time.process_time() 以獲得具有良好定義的行為。 (由 Matthias Bussonnier 在 bpo-36895 中貢獻。)

  • pyvenv 腳本已被移除,推薦改用 python3.8 -m venv 來幫助消除容易混淆 pyvenv 腳本所關聯的 Python 解釋器這一問題。 (由 Brett Cannon 在 bpo-25427 中貢獻。)

  • parse_qsparse_qsl 和 escape 已從 cgi 模塊中被移除。 這些函數自 Python 3.2 或更早就已被棄用。 它們應改為從 urllib.parse 和 html 模塊導入。

  • filemode 函數已從 tarfile 模塊中被移除。 該函數未被寫入文檔,自 Python 3.3 起就已棄用。

  • XMLParser 構造器不再接受 html 參數。 它從來沒有任何作用並在 Python 3.4 中已被棄用。 所有其他形參現在都是 僅限關鍵字參數。 (由 Serhiy Storchaka 在 bpo-29209 中貢獻。)

  • XMLParser 的 doctype() 方法已被移除。 (由 Serhiy Storchaka 在 bpo-29209 中貢獻。)

  • "unicode_internal" 編解碼器已被移除。 (由 Inada Naoki 在 bpo-36297 中貢獻。)

  • sqlite3 模塊的 Cache 和 Statement 對象已不再公開給用戶。 (由 Aviv Palivoda 在 bpo-30262 中貢獻。)

  • fileinput.input() 和 fileinput.FileInput() 中自 Python 3.6 起就已被忽略並棄用的 bufsize 關鍵字參數已被移除。 由 Matthias Bussonnier 在 bpo-36952 中貢獻。)

  • 在 Python 3.7 中棄用的函數 sys.set_coroutine_wrapper() 和 sys.get_coroutine_wrapper() 已被移除。 (由 Matthias Bussonnier 在 bpo-36933 中貢獻。)

移植到 Python 3.8

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

Python 行為的改變

  • yield 表達式(包括 yield 和 yield from 子句)現在不允許在推導式和生成器表達式中使用(但 for 子句最左邊的可迭代對象表達式除外)。 (由 Serhiy Storchaka 在 bpo-10544 中貢獻。)

  • 當標識號檢測 (is 和 is not) 與特定類型的字面值 (例如字符串和數字) 一同使用時編譯器現在會產生 SyntaxWarning。 這在 CPython 中通常是可行的,但並不被語言定義所保證。 該警告會建議用戶改用相等性檢測 (== and !=)。 (由 Serhiy Storchaka 在 bpo-34850 中貢獻。)

  • CPython 解釋器在某些情況下可以忽略異常。 在 Python 3.8 中這種情況會更少發生。 特別地,從類型字典獲取屬性時引發的異常不會再被忽略。 (由 Serhiy Storchaka 在 bpo-35459 中貢獻。)

  • 從內置類型 boolintfloatcomplex 和標准庫的一些類中移除了 __str__ 實現。 它們現在會從 object 繼承 __str__()。 作為結果,在這些類的子類中定義 __repr__() 方法將會影響它們的字符串表示。 (由 Serhiy Storchaka 在 bpo-36793 中貢獻。)

  • 在 AIX 上,sys.platform 將不再包含主要版本號。 它將總是 'aix' 而不再是 'aix3' .. 'aix7'。 由於較舊的 Python 版本會包含該版本號,因此推薦總是使用 sys.platform.startswith('aix')。 (由 M. Felt 在 bpo-36588 中貢獻。)

  • 現在 PyEval_AcquireLock() 和 PyEval_AcquireThread() 如果當解釋器終結化時被調用將會終結當前線程,以使它們與 PyEval_RestoreThread()Py_END_ALLOW_THREADS() 以及 PyGILState_Ensure() 保持一致。 如果不想要這樣的行為,請通過檢測 _Py_IsFinalizing() 或 sys.is_finalizing() 來保護該調用。 (由 Joannah Nanjekye 在 bpo-36475 中貢獻。)

更改的Python API

  • 在 Windows 上 os.getcwdb() 函數現在會使用 UTF-8 編碼格式而不是 ANSI 代碼頁:請參看 PEP 529 了解具體原因。 該函數在 Windows 上不再被棄用。 (由 Victor Stinner 在 bpo-37412 中貢獻。)

  • 現在 subprocess.Popen 在某些情況下會使用 os.posix_spawn() 以獲得更好的性能。 在適用於 Linux 的 Windows 子系統和 QEMU 用戶模擬器上,使用 os.posix_spawn() 的 Popen 構造器不會再因為“找不到程序”這樣的錯誤引發異常。 而是讓子進程失敗並返回一個非零的 returncode。 (由 Joannah Nanjekye 和 Victor Stinner 在 bpo-35537 中貢獻。)

  • The preexec_fn argument of * subprocess.Popen is no longer compatible with subinterpreters. The use of the parameter in a subinterpreter now raises RuntimeError. (Contributed by Eric Snow in bpo-34651, modified by Christian Heimes in bpo-37951.)

  • imap.IMAP4.logout() 方法不會再靜默地忽略任意異常。 (由 Victor Stinner 在 bpo-36348 中貢獻。)

  • 函數 platform.popen() 已被移除,它自 Python 3.3 起就已被棄用:請改用 os.popen()。 (由 Victor Stinner 在 bpo-35345 中貢獻。)

  • 當傳入多模數據時 statistics.mode() 函數不會再引發異常。 它將改為返回在輸入數據中遇到的第一個模式。 (由 Raymond Hettinger 在 bpo-35892 中貢獻。)

  • tkinter.ttk.Treeview 類的 selection() 方法不再接受參數。 帶參數調用該方法來改變選擇在 Python 3.6 中已棄用。 請使用專門方法例如 selection_set() 來改變選擇。 (由 Serhiy Storchaka 在 bpo-31508 中貢獻。)

  • xml.dom.minidom 的 writexml()toxml() 和 toprettyxml() 方法以及 xml.etree 的 write() 方法現在會保留用戶指定的屬性順序。 (由 Diego Rojas 和 Raymond Hettinger 在 bpo-34160 中貢獻。)

  • 附帶 'r' 旗標打開的 dbm.dumb 數據庫現在將是只讀的。 如果數據庫不存在,附帶 'r' 和 'w' 旗標的 dbm.dumb.open() 不會再創建數據庫。 (由 Serhiy Storchaka 在 bpo-32749 中貢獻。)

  • 在 XMLParser 的子類中定義的 doctype() 方法將不會再被調用,並將導致發出 RuntimeWarning 而不是 DeprecationWarning。 請在目標上定義 doctype() 方法來處理 XML doctype 聲明。 (由 Serhiy Storchaka 在 bpo-29209 中貢獻。)

  • 現在當自定義元類未在傳給 type.__new__ 的命名空間中提供 __classcell__ 入口時將引發 RuntimeError。 在 Python 3.6--3.7 中是則是引發 DeprecationWarning。 (由 Serhiy Storchaka 在 bpo-23722 中貢獻。)

  • cProfile.Profile 類現在可被用作上下文管理器。 (由 Scott Sanderson 在 bpo-29235 中貢獻。)

  • shutil.copyfile()shutil.copy()shutil.copy2()shutil.copytree() 和 shutil.move() 會使用平台專屬的 "fast-copy" 系統調用(參見 依賴於具體平台的高效拷貝操作 一節)。

  • shutil.copyfile() 在 Windows 上的默認緩沖區大小從 16 KiB 改為 1 MiB。

  • PyGC_Head 結構已被完全改變。 所有接觸到該結構的代碼都應當被重寫。 (參見 bpo-33597。)

  • PyInterpreterState 結構已被移入 "internal" 頭文件(特別是 Include/internal/pycore_pystate.h)。 不透明的 PyInterpreterState 作為僅有 API(以及穩定版 ABI)的一部分仍然可用。 文檔指明該結構的任何字段都不是公有的,因此我們希望沒人在使用它們。 但是,如果你確實依賴其中某一個或更多個私有字段並且沒有其他替代選項,則請開一個 BPO 問題。 我們將盡力幫助你進行調整(可能包括向公有 API 添加訪問器函數)。 (參見 bpo-35886。)

  • 現在所有平台下的 mmap.flush() 方法都會在成功時返回 None 並在錯誤時引發異常。 之前它的行為取決於具體平台: Windows 下會在成功時返回非零值;在失敗時返回零。 Unix 下會在成功時返回零;在失敗時引發錯誤。 (由 Berker Peksag 在 bpo-2122 中貢獻。)

  • xml.dom.minidom 和 xml.sax 模塊默認將不再處理外部實體。 (由 Christian Heimes 在 bpo-17239 中貢獻。)

  • 從只讀的 dbm 數據庫 (dbm.dumbdbm.gnu 或 dbm.ndbm) 刪除鍵將會引發 error (dbm.dumb.errordbm.gnu.error 或 dbm.ndbm.error) 而不是 KeyError。 (由 Xiang Zhang 在 bpo-33106 中貢獻。)

  • Simplified AST for literals. All constants will be represented as ast.Constant instances. Instantiating old classes NumStrBytesNameConstant and Ellipsis will return an instance of Constant. (Contributed by Serhiy Storchaka in bpo-32892.)

  • expanduser() 在 Windows 上現在改用 USERPROFILE 環境變量而不再使用 HOME,后者通常不會為一般用戶賬戶設置。 (由 Anthony Sottile 在 bpo-36264 中貢獻。)

  • The exception asyncio.CancelledError now inherits from BaseException rather than Exception. (Contributed by Yury Selivanov in bpo-32528.)

  • The function asyncio.wait_for() now correctly waits for cancellation when using an instance of asyncio.Task. Previously, upon reaching timeout, it was cancelled and immediately returned. (Contributed by Elvis Pranskevichus in bpo-32751.)

  • The function asyncio.BaseTransport.get_extra_info() now returns a safe to use socket object when 'socket' is passed to the name parameter. (Contributed by Yury Selivanov in bpo-37027.)

  • asyncio.BufferedProtocol has graduated to the stable API.

  • DLL dependencies for extension modules and DLLs loaded with ctypes on Windows are now resolved more securely. Only the system paths, the directory containing the DLL or PYD file, and directories added with add_dll_directory() are searched for load-time dependencies. Specifically, PATH and the current working directory are no longer used, and modifications to these will no longer have any effect on normal DLL resolution. If your application relies on these mechanisms, you should check for add_dll_directory() and if it exists, use it to add your DLLs directory while loading your library. Note that Windows 7 users will need to ensure that Windows Update KB2533623 has been installed (this is also verified by the installer). (Contributed by Steve Dower in bpo-36085.)

  • 關聯到 pgen 的頭文件和函數在其被純 Python 實現取代后已被移除。 (由 Pablo Galindo 在 bpo-36623 中貢獻。)

  • types.CodeType 在構造器的第二個位置新增了一個形參 (posonlyargcount) 以支持在 PEP 570 中定義的僅限位置參數。 第一個參數 (argcount) 現在表示位置參數的總數量 (包括僅限位置參數)。 types.CodeType 中新增的 replace() 方法可用於讓代碼支持 future 特性。

C API 中的改變

  • PyCompilerFlags 結構體添加了一個新的 cf_feature_version 字段。 它應當被初始化為 PY_MINOR_VERSION。 該字段默認會被忽略,當且僅當 PyCF_ONLY_AST 在 cf_flags 中設置旗標時才會被使用。 (由 Guido van Rossum 在 bpo-35766 中貢獻。)

  • PyEval_ReInitThreads() 函數已從 C API 中移除。 它不應當被顯式地調用;請改用 PyOS_AfterFork_Child()。 (由 Victor Stinner 在 bpo-36728 中貢獻。)

  • 在 Unix 上,C 擴展不會再被鏈接到 libpython,但 Android 和 Cygwin 例外。 當 Python 被嵌入時,libpython 不可使用 RTLD_LOCAL 加載,而要改用 RTLD_GLOBAL。 之前使用 RTLD_LOCAL 已經不可能加載未鏈接到 libpython 的 C 擴展了,例如通過 Modules/Setup 的 *shared* 部分構建的標准庫 C 擴展。 (由 Victor Stinner 在 bpo-21536 中貢獻。)

  • 在解析或構建值時(例如 PyArg_ParseTuple()Py_BuildValue()PyObject_CallFunction() 等等)使用形如 # 的格式而不定義 PY_SSIZE_T_CLEAN 現在將會引發 DeprecationWarning。 它將在 3.10 或 4.0 中被移除。 請參閱 語句解釋及變量編譯 了解詳情。 (由 Inada Naoki 在 bpo-36381 中貢獻。)

  • 堆分配類型的實例(例如使用 PyType_FromSpec() 創建的實例)會保存一個對其類型對象的引用。 提升這些類型對象引用計數的操作已從 PyType_GenericAlloc() 移至更低層級的函數 PyObject_Init() 和 PyObject_INIT()。 這使用通過This makes types created through PyType_FromSpec() 所創建類型的行為與管理代碼中的其他類保持一致。

    靜態分配類型將不受影響。

    在大部分情況下,這應該都不會有附帶影響。 但是,在分配實例后手動提升引用計數的類型(也許是為了繞過漏洞)現在可能永遠不會被銷毀。 要避免這種情況,這些類需要在實例撤銷分配期間在類型對象上調用 Py_DECREF。

    要正確地將這些類型移植到 3.8,請應用以下修改:

    • 在分配實例之后在類型對象上移除 Py_INCREF —— 如果有的話。 這可以發生在調用 PyObject_New()PyObject_NewVar()PyObject_GC_New()PyObject_GC_NewVar() 或任何其他使用 PyObject_Init() 或 PyObject_INIT() 的自定義分配器之后。

      示例:

      static foo_struct * foo_new(PyObject *type) { foo_struct *foo = PyObject_GC_New(foo_struct, (PyTypeObject *) type); if (foo == NULL) return NULL; #if PY_VERSION_HEX < 0x03080000 // Workaround for Python issue 35810; no longer necessary in Python 3.8 PY_INCREF(type) #endif return foo; } 
    • 確保所有堆分配類型的自定義 tp_dealloc 函數會減少類型的引用計數。

      示例:

      static void foo_dealloc(foo_struct *instance) { PyObject *type = Py_TYPE(instance); PyObject_GC_Del(instance); #if PY_VERSION_HEX >= 0x03080000 // This was not needed before Python 3.8 (Python issue 35810) Py_DECREF(type); #endif } 

    (由 Eddie Elizondo 在 bpo-35810 中貢獻。)

  • Py_DEPRECATED() 宏已經針對 MSVC 實現。 這個宏現在必須放在符號名稱之前。

    示例:

    Py_DEPRECATED(3.8) PyAPI_FUNC(int) Py_OldFunction(void); 

    (由 Zackery Spytz 在 bpo-33407 中貢獻。)

  • 解釋器將不再假裝支持跨發布版本的擴展類型二進制兼容性。 由第三方擴展模塊所導出的 PyTypeObject 應該具有當前 Python 版本所要求的所有空位,包括 tp_finalize (Py_TPFLAGS_HAVE_FINALIZE 不會再在讀取 tp_finalize 之前被檢查)。

    (由 Antoine Pitrou 在 bpo-32388 中貢獻。)

  • PyCode_New() 在第二個位置添加了新的形參 (posonlyargcount) 以支持 PEP 570,指明僅限位置參數的數量。

  • 函數 PyNode_AddChild() 和 PyParser_AddToken() 現在接受兩個額外的 int 參數 end_lineno 和 end_col_offset

  • 允許 MinGW 工具直接鏈接到 python38.dll 的 libpython38.a 文件已不再包含於標准的 Windows 分發包中。 如果你需要此文件,可使用 gendef 和 dlltool 工具來生成它,這些工具是 MinGW binutils 包的一部分:

    gendef - python38.dll > tmp.def
    dlltool --dllname python38.dll --def tmp.def --output-lib libpython38.a
    

    已安裝的 pythonXY.dll 所在位置將取決於安裝選項以及 Windows 的版本和語言。 請參閱 在Windows上使用 Python 了解更多信息。 該結果庫應當放在與 pythonXY.lib 相同的目錄下,這通常是你的 Python 安裝路徑下的 libs 目錄。

    (由 Steve Dower 在 bpo-37351 中貢獻。)

CPython 字節碼的改變

  • 解釋器循環已通過將塊堆棧展開邏輯移入編譯器獲得了簡化。 編譯器現在會發出顯式指令來調整值堆棧並為 breakcontinue 和 return 調用清除代碼。

    移除了操作碼 BREAK_LOOPCONTINUE_LOOPSETUP_LOOP 和 SETUP_EXCEPT。 添加了新的操作碼 ROT_FOURBEGIN_FINALLYCALL_FINALLY 和 POP_FINALLY。 修改了 END_FINALLY 和 WITH_CLEANUP_START 的行為。

    (由 Mark Shannon, Antoine Pitrou 和 Serhiy Storchaka 在 bpo-17611 中貢獻。)

  • 添加了新的操作碼 END_ASYNC_FOR 用於處理當等待 async for 循環的下一項時引發的異常。 (由 Serhiy Storchaka 在 bpo-33041 中貢獻。)

  • MAP_ADD 現在會預期值為棧的第一個元素而鍵為第二個元素。 作出此改變以使得字典推導式能如 PEP 572 所提議的那樣,鍵總是會在值之前被求值。 (由 Jörn Heissler 在 bpo-35224 中貢獻。)

演示和工具

添加了一個檢測腳本用於對訪問變量的不同方式進行計時: Tools/scripts/var_access_benchmark.py。 (由 Raymond Hettinger 在 bpo-35884 中貢獻。)

Here's a summary of performance improvements since Python 3.3:

Python version                       3.3     3.4     3.5     3.6     3.7     3.8
--------------                       ---     ---     ---     ---     ---     ---

Variable and attribute read access:
    read_local                       4.0     7.1     7.1     5.4     5.1     3.9
    read_nonlocal                    5.3     7.1     8.1     5.8     5.4     4.4
    read_global                     13.3    15.5    19.0    14.3    13.6     7.6
    read_builtin                    20.0    21.1    21.6    18.5    19.0     7.5
    read_classvar_from_class        20.5    25.6    26.5    20.7    19.5    18.4
    read_classvar_from_instance     18.5    22.8    23.5    18.8    17.1    16.4
    read_instancevar                26.8    32.4    33.1    28.0    26.3    25.4
    read_instancevar_slots          23.7    27.8    31.3    20.8    20.8    20.2
    read_namedtuple                 68.5    73.8    57.5    45.0    46.8    18.4
    read_boundmethod                29.8    37.6    37.9    29.6    26.9    27.7

Variable and attribute write access:
    write_local                      4.6     8.7     9.3     5.5     5.3     4.3
    write_nonlocal                   7.3    10.5    11.1     5.6     5.5     4.7
    write_global                    15.9    19.7    21.2    18.0    18.0    15.8
    write_classvar                  81.9    92.9    96.0   104.6   102.1    39.2
    write_instancevar               36.4    44.6    45.8    40.0    38.9    35.5
    write_instancevar_slots         28.7    35.6    36.1    27.3    26.6    25.7

Data structure read access:
    read_list                       19.2    24.2    24.5    20.8    20.8    19.0
    read_deque                      19.9    24.7    25.5    20.2    20.6    19.8
    read_dict                       19.7    24.3    25.7    22.3    23.0    21.0
    read_strdict                    17.9    22.6    24.3    19.5    21.2    18.9

Data structure write access:
    write_list                      21.2    27.1    28.5    22.5    21.6    20.0
    write_deque                     23.8    28.7    30.1    22.7    21.8    23.5
    write_dict                      25.9    31.4    33.3    29.3    29.2    24.7
    write_strdict                   22.9    28.4    29.9    27.5    25.2    23.1

Stack (or queue) operations:
    list_append_pop                144.2    93.4   112.7    75.4    74.2    50.8
    deque_append_pop                30.4    43.5    57.0    49.4    49.2    42.5
    deque_append_popleft            30.8    43.7    57.3    49.7    49.7    42.8

Timing loop:
    loop_overhead                    0.3     0.5     0.6     0.4     0.3     0.3

(Measured from the macOS 64-bit builds found at python.org)

Python 3.8.1 中的重要變化

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

Notable changes in Python 3.8.2

Fixed a regression with the ignore callback of shutil.copytree(). The argument types are now str and List[str] again. (Contributed by Manuel Barkhau and Giampaolo Rodola in bpo-39390.)


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM