Python 3.8 有什么新變化?
- 編者
Raymond Hettinger(譯者:wh2099 at outlook dot com)
本文解釋了 Python 3.8 相比 3.7 的新增特性。 完整的詳情可參閱 更新日志。
摘要 -- 發(fā)布重點(diǎn)?
新的特性?
賦值表達(dá)式?
新增的語法 :=
可在表達(dá)式內(nèi)部為變量賦值。 它被昵稱為“海象運(yùn)算符”因?yàn)樗芟袷?海象的眼睛和長(zhǎng)牙。
在這個(gè)示例中,賦值表達(dá)式可以避免調(diào)用 len()
兩次:
if (n := len(a)) > 10:
print(f"List is too long ({n} elements, expected <= 10)")
類似的益處還可出現(xiàn)在正則表達(dá)式匹配中需要使用兩次匹配對(duì)象的情況中,一次檢測(cè)用于匹配是否發(fā)生,另一次用于提取子分組:
discount = 0.0
if (mo := re.search(r'(\d+)% discount', advertisement)):
discount = float(mo.group(1)) / 100.0
此運(yùn)算符也適用于配合 while 循環(huán)計(jì)算一個(gè)值來檢測(cè)循環(huán)是否終止,而同一個(gè)值又在循環(huán)體中再次被使用的情況:
# Loop over fixed length blocks
while (block := f.read(256)) != '':
process(block)
另一個(gè)值得介紹的用例出現(xiàn)于列表推導(dǎo)式中,在篩選條件中計(jì)算一個(gè)值,而同一個(gè)值又在表達(dá)式中需要被使用:
[clean_name.title() for name in names
if (clean_name := normalize('NFC', name)) in allowed_names]
請(qǐng)盡量將海象運(yùn)算符的使用限制在清晰的場(chǎng)合中,以降低復(fù)雜性并提升可讀性。
請(qǐng)參閱 PEP 572 了解詳情。
(由 Morehouse 在 bpo-35224 中貢獻(xiàn)。)
僅限位置形參?
新增了一個(gè)函數(shù)形參語法 /
用來指明某些函數(shù)形參必須使用僅限位置而非關(guān)鍵字參數(shù)的形式。 這種標(biāo)記語法與通過 help()
所顯示的使用 Larry Hastings 的 Argument Clinic 工具標(biāo)記的 C 函數(shù)相同。
在下面的例子中,形參 a 和 b 為僅限位置形參,c 或 d 可以是位置形參或關(guān)鍵字形參,而 e 或 f 要求為關(guān)鍵字形參:
def f(a, b, /, c, d, *, e, f):
print(a, b, c, d, e, f)
以下均為合法的調(diào)用:
f(10, 20, 30, d=40, e=50, f=60)
但是,以下均為不合法的調(diào)用:
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
這種標(biāo)記形式的一個(gè)用例是它允許純 Python 函數(shù)完整模擬現(xiàn)有的用 C 代碼編寫的函數(shù)的行為。 例如,內(nèi)置的 divmod()
函數(shù)不接受關(guān)鍵字參數(shù):
def divmod(a, b, /):
"Emulate the built in divmod() function"
return (a // b, a % b)
另一個(gè)用例是在不需要形參名稱時(shí)排除關(guān)鍵字參數(shù)。 例如,內(nèi)置的 len()
函數(shù)的簽名為 len(obj, /)
。 這可以排除如下這種笨拙的調(diào)用形式:
len(obj='hello') # The "obj" keyword argument impairs readability
另一個(gè)益處是將形參標(biāo)記為僅限位置形參將允許在未來修改形參名而不會(huì)破壞客戶的代碼。 例如,在 statistics
模塊中,形參名 dist 在未來可能被修改。 這使得以下函數(shù)描述成為可能:
def quantiles(dist, /, *, n=4, method='exclusive')
...
由于在 /
左側(cè)的形參不會(huì)被公開為可用關(guān)鍵字,其他形參名仍可在 **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}
這極大地簡(jiǎn)化了需要接受任意關(guān)鍵字參數(shù)的函數(shù)和方法的實(shí)現(xiàn)。 例如,以下是一段摘自 collections
模塊的代碼:
class Counter(dict):
def __init__(self, iterable=None, /, **kwds):
# Note "iterable" is a possible keyword argument
請(qǐng)參閱 PEP 570 了解詳情。
(由 Pablo Galindo 在 bpo-36540 中貢獻(xiàn)。)
用于已編譯字節(jié)碼文件的并行文件系統(tǒng)緩存?
新增的 PYTHONPYCACHEPREFIX
設(shè)置 (也可使用 -X
pycache_prefix
) 可將隱式的字節(jié)碼緩存配置為使用單獨(dú)的并行文件系統(tǒng)樹,而不是默認(rèn)的每個(gè)源代碼目錄下的 __pycache__
子目錄。
緩存的位置會(huì)在 sys.pycache_prefix
中報(bào)告 (None
表示默認(rèn)位置即 __pycache__
子目錄)。
(由 Carl Meyer 在 bpo-33499 中貢獻(xiàn)。)
調(diào)試構(gòu)建使用與發(fā)布構(gòu)建相同的 ABI?
Python 現(xiàn)在不論是以發(fā)布模式還是調(diào)試模式進(jìn)行構(gòu)建都將使用相同的 ABI。 在 Unix 上,當(dāng) Python 以調(diào)試模式構(gòu)建時(shí),現(xiàn)在將可以加載以發(fā)布模式構(gòu)建的 C 擴(kuò)展和使用穩(wěn)定版 ABI 構(gòu)建的 C 擴(kuò)展。
發(fā)布編譯版和 調(diào)試編譯版 現(xiàn)在都是 ABI 兼容的:定義 Py_DEBUG
宏不會(huì)再應(yīng)用 Py_TRACE_REFS
宏,它引入 了唯一的 ABI 不兼容性。 Py_TRACE_REFS
宏添加了 sys.getobjects()
函數(shù)和 PYTHONDUMPREFS
環(huán)境變量,它可以使用新的 ./configure --with-trace-refs
編譯選項(xiàng)來設(shè)置。 (由 Victor Stinner 在 bpo-36465 中貢獻(xiàn)。)
在 Unix 上,C 擴(kuò)展不會(huì)再被鏈接到 libpython,但 Android 和 Cygwin 例外。 現(xiàn)在靜態(tài)鏈接的 Python 將可以加載使用共享庫(kù) Python 構(gòu)建的 C 擴(kuò)展。 (由 Victor Stinner 在 bpo-21536 中貢獻(xiàn)。)
在 Unix 上,當(dāng) Python 以調(diào)試模式構(gòu)建時(shí),導(dǎo)入操作現(xiàn)在也會(huì)查找在發(fā)布模式下編譯的 C 擴(kuò)展以及使用穩(wěn)定版 ABI 編譯的 C 擴(kuò)展。 (由 Victor Stinner 在 bpo-36722 中貢獻(xiàn)。)
要將 Python 嵌入到一個(gè)應(yīng)用中,必須將新增的 --embed
選項(xiàng)傳給 python3-config --libs --embed
以獲得 -lpython3.8
(將應(yīng)用鏈接到 libpython)。 要同時(shí)支持 3.8 和舊版本,請(qǐng)先嘗試 python3-config --libs --embed
并在此命令失敗時(shí)回退到 python3-config --libs
(即不帶 --embed
)。
增加一個(gè) pkg-config python-3.8-embed
模塊用來將 Python 嵌入到一個(gè)應(yīng)用中: pkg-config python-3.8-embed --libs
包含 -lpython3.8
。 要同時(shí)支持 3.8 和舊版本,請(qǐng)先嘗試 pkg-config python-X.Y-embed --libs
并在此命令失敗時(shí)回退到 pkg-config python-X.Y --libs
(即不帶 --embed
) (請(qǐng)將 X.Y
替換為 Python 版本號(hào))。
另一方面,pkg-config python3.8 --libs
不再包含 -lpython3.8
。 C 擴(kuò)展不可被鏈接到 libpython (但 Android 和 Cygwin 例外,這兩者的情況由腳本處理);此改變是故意被設(shè)為向下不兼容的。 (由 Victor Stinner 在 bpo-36721 中貢獻(xiàn)。)
f-字符串支持 =
用于自動(dòng)記錄表達(dá)式和調(diào)試文檔?
增加 =
說明符用于 f-string。 形式為 f'{expr=}'
的 f-字符串將擴(kuò)展表示為表達(dá)式文本,加一個(gè)等于號(hào),再加表達(dá)式的求值結(jié)果。 例如:
>>> user = 'eric_idle'
>>> member_since = date(1975, 7, 31)
>>> f'{user=} {member_since=}'
"user='eric_idle' member_since=datetime.date(1975, 7, 31)"
通常的 f-字符串格式說明符 允許更細(xì)致地控制所要顯示的表達(dá)式結(jié)果:
>>> delta = date.today() - member_since
>>> f'{user=!s} {delta.days=:,d}'
'user=eric_idle delta.days=16,075'
=
說明符將輸出整個(gè)表達(dá)式,以便詳細(xì)演示計(jì)算過程:
>>> print(f'{theta=} {cos(radians(theta))=:.3f}')
theta=30 cos(radians(theta))=0.866
(由 Eric V. Smith 和 Larry Hastings 在 bpo-36817 中貢獻(xiàn)。)
PEP 578: Python 運(yùn)行時(shí)審核鉤子?
此 PEP 添加了審核鉤子和已驗(yàn)證開放鉤子。 兩者在 Python 與本機(jī)代碼中均可用。允許以純 Python 代碼編寫的應(yīng)用和框架利用額外的通知,同時(shí)允許嵌入開發(fā)人員或系統(tǒng)管理員部署始終啟用審核的 Python 版本。
請(qǐng)參閱 PEP 578 了解詳情。
PEP 587: Python 初始化配置?
PEP 587 增加了一個(gè)新的 C API 用來配置 Python 初始化,提供對(duì)整個(gè)配置過程的更細(xì)致控制以及更好的錯(cuò)誤報(bào)告。
新的結(jié)構(gòu):
新的函數(shù):
PyConfig_Clear()
PyConfig_InitIsolatedConfig()
PyConfig_InitPythonConfig()
PyConfig_Read()
PyConfig_SetArgv()
PyConfig_SetBytesArgv()
PyConfig_SetBytesString()
PyConfig_SetString()
PyPreConfig_InitIsolatedConfig()
PyPreConfig_InitPythonConfig()
PyStatus_Error()
PyStatus_Exception()
PyStatus_Exit()
PyStatus_IsError()
PyStatus_IsExit()
PyStatus_NoMemory()
PyStatus_Ok()
PyWideStringList_Append()
PyWideStringList_Insert()
Py_ExitStatusException()
此 PEP 還為這些內(nèi)部結(jié)構(gòu)添加了 _PyRuntimeState.preconfig
(PyPreConfig
類型) 和 PyInterpreterState.config
(PyConfig
類型) 字段。 PyInterpreterState.config
成為新的引用配置,替代全局配置變量和其他私有變量。
請(qǐng)參閱 Python 初始化配置 獲取詳細(xì)文檔。
請(qǐng)參閱 PEP 587 了解詳情。
(由 Victor Stinner 在 bpo-36763 中貢獻(xiàn)。)
PEP 590: Vectorcall: 用于 CPython 的快速調(diào)用協(xié)議?
將 Vectorcall 協(xié)議 添加到 Python/C API。 它的目標(biāo)是對(duì)已被應(yīng)用于多個(gè)類的現(xiàn)有優(yōu)先進(jìn)行正式化。 任何實(shí)現(xiàn)了可調(diào)用對(duì)象的 靜態(tài)類型 均可使用此協(xié)議。
此特性目前為暫定狀態(tài),計(jì)劃在 Python 3.9 將其完全公開。
請(qǐng)參閱 PEP 590 了解詳情。
(由 Jeroen Demeyer, Mark Shannon 和 Petr Viktorin 在 bpo-36974 中貢獻(xiàn)。)
具有外部數(shù)據(jù)緩沖區(qū)的 pickle 協(xié)議 5?
當(dāng)使用 pickle
在 Python 進(jìn)程間傳輸大量數(shù)據(jù)以充分發(fā)揮多核或多機(jī)處理的優(yōu)勢(shì)時(shí),非常重要一點(diǎn)是通過減少內(nèi)存拷貝來優(yōu)化傳輸效率,并可能應(yīng)用一些定制技巧例如針對(duì)特定數(shù)據(jù)的壓縮。
pickle
協(xié)議 5 引入了對(duì)于外部緩沖區(qū)的支持,這樣 PEP 3118 兼容的數(shù)據(jù)可以與主 pickle 流分開進(jìn)行傳輸,這是由通信層來確定的。
請(qǐng)參閱 PEP 574 了解詳情。
(由 Antoine Pitrou 在 bpo-36785 中貢獻(xiàn)。)
其他語言特性修改?
在之前版本中
continue
語句不允許在finally
子句中使用,這是因?yàn)榫唧w實(shí)現(xiàn)存在一個(gè)問題。 在 Python 3.8 中此限制已被取消。 (由 Serhiy Storchaka 在 bpo-32489 中貢獻(xiàn)。)bool
,int
和fractions.Fraction
類型現(xiàn)在都有一個(gè)as_integer_ratio()
方法,與float
和decimal.Decimal
中的已有方法類似。 這個(gè)微小的 API 擴(kuò)展使得numerator, denominator = x.as_integer_ratio()
這樣的寫法在多種數(shù)字類型上通用成為可能。 (由 Lisa Roach 在 bpo-33073 和 Raymond Hettinger 在 bpo-37819 中貢獻(xiàn)。)int
,float
和complex
的構(gòu)造器現(xiàn)在會(huì)使用__index__()
特殊方法,如果該方法可用而對(duì)應(yīng)的方法 method__int__()
,__float__()
或__complex__()
方法不可用的話。 (由 Serhiy Storchaka 在 bpo-20092 中貢獻(xiàn)。)添加
\N{name}
轉(zhuǎn)義符在正則表達(dá)式
中的支持:>>> 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 中貢獻(xiàn)。)
現(xiàn)在 dict 和 dictview 可以使用
reversed()
按插入順序反向迭代。 (由 Rémi Lapeyre 在 bpo-33462 中貢獻(xiàn)。)在函數(shù)調(diào)用中允許使用的關(guān)鍵字名稱語法受到進(jìn)一步的限制。 特別地,
f((keyword)=arg)
不再被允許。 關(guān)鍵字參數(shù)賦值形式的左側(cè)絕不允許一般標(biāo)識(shí)符以外的其他內(nèi)容。 (由 Benjamin Peterson 在 bpo-34641 中貢獻(xiàn)。)在
yield
和return
語句中的一般可迭代對(duì)象解包不再要求加圓括號(hào)。 這使得 yield 和 return 的語法與正常的賦值語法更為一致:>>> def parse(family): lastname, *members = family.split() return lastname.upper(), *members >>> parse('simpsons homer marge bart lisa maggie') ('SIMPSONS', 'homer', 'marge', 'bart', 'lisa', 'maggie')
(由 David Cuthbert 和 Jordan Chapman 在 bpo-32117 中貢獻(xiàn)。)
當(dāng)類似
[(10, 20) (30, 40)]
這樣在代碼中少了一個(gè)逗號(hào)時(shí),編譯器將顯示SyntaxWarning
并附帶更有幫助的提示。 這相比原來用TypeError
來提示第一個(gè)元組是不可調(diào)用的更容易被理解。 (由 Serhiy Storchaka 在 bpo-15248 中貢獻(xiàn)。)datetime.date
或datetime.datetime
和datetime.timedelta
對(duì)象之間的算術(shù)運(yùn)算現(xiàn)在將返回相應(yīng)子類的實(shí)例而不是基類的實(shí)例。 這也會(huì)影響到在具體實(shí)現(xiàn)中(直接或間接地)使用了datetime.timedelta
算術(shù)運(yùn)算的返回類型,例如astimezone()
。 (由 Paul Ganssle 在 bpo-32417 中貢獻(xiàn)。)當(dāng) Python 解釋器通過 Ctrl-C (SIGINT) 被中斷并且所產(chǎn)生的
KeyboardInterrupt
異常未被捕獲,Python 進(jìn)程現(xiàn)在會(huì)通過一個(gè) SIGINT 信號(hào)或是使得發(fā)起調(diào)用的進(jìn)程能檢測(cè)到它是由 Ctrl-C 操作殺死的正確退出代碼來退出。 POSIX 和 Windows 上的終端會(huì)相應(yīng)地使用此代碼在交互式會(huì)話中終止腳本。 (由 Google 的 Gregory P. Smith 在 bpo-1054041 中貢獻(xiàn)。)某些高級(jí)編程風(fēng)格要求為現(xiàn)有的函數(shù)更新
types.CodeType
對(duì)象。 由于代碼對(duì)象是不可變的,需要基于現(xiàn)有代碼對(duì)象模型創(chuàng)建一個(gè)新的代碼對(duì)象。 使用 19 個(gè)形參將會(huì)相當(dāng)繁瑣。 現(xiàn)在,新的replace()
方法使得通過少量修改的形參創(chuàng)建克隆對(duì)象成為可能。下面是一個(gè)修改
statistics.mean()
函數(shù)來防止 data 形參被用作關(guān)鍵字參數(shù)的例子:>>> 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 中貢獻(xiàn)。)
對(duì)于整數(shù),現(xiàn)在
pow()
函數(shù)的三參數(shù)形式在底數(shù)與模數(shù)不可約的情況下允許指數(shù)為負(fù)值。 隨后它會(huì)在指數(shù)為-1
時(shí)計(jì)算底數(shù)的模乘逆元,并對(duì)其他負(fù)指數(shù)計(jì)算反模的適當(dāng)冪次。 例如,要計(jì)算 38 模 137 的 模乘逆元 則可寫為:>>> pow(38, -1, 137) 119 >>> 119 * 38 % 137 1
模乘逆元在求解 線性丟番圖方程 會(huì)被用到。 例如,想要求出
4258?? + 147?? = 369
的整數(shù)解,首先應(yīng)重寫為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 中貢獻(xiàn)。)
字典推導(dǎo)式已與字典字面值實(shí)現(xiàn)同步,會(huì)先計(jì)算鍵再計(jì)算值:
>>> # 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
對(duì)執(zhí)行順序的保證對(duì)賦值表達(dá)式來說很有用,因?yàn)樵阪I表達(dá)式中賦值的變量將可在值表達(dá)式中被使用:
>>> 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 中貢獻(xiàn)。)
object.__reduce__()
方法現(xiàn)在可返回長(zhǎng)度為二至六個(gè)元素的元組。 之前的上限為五個(gè)。 新增的第六個(gè)可選元素是簽名為(obj, state)
的可調(diào)用對(duì)象。 這樣就允許直接控制特定對(duì)象的狀態(tài)更新。 如果元素值不為 None,該可調(diào)用對(duì)象將優(yōu)先于對(duì)象的__setstate__()
方法。 (由 Pierre Glaser 和 Olivier Grisel 在 bpo-35900 中貢獻(xiàn)。)
新增模塊?
新增的
importlib.metadata
模塊提供了從第三方包讀取元數(shù)據(jù)的(臨時(shí))支持。 例如,它可以提取一個(gè)已安裝軟件包的版本號(hào)、入口點(diǎn)列表等等:>>> # 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 中貢獻(xiàn))。
改進(jìn)的模塊?
ast?
AST 節(jié)點(diǎn)現(xiàn)在具有 end_lineno
和 end_col_offset
屬性,它們給出節(jié)點(diǎn)結(jié)束的精確位置。 (這只適用于具有 lineno
和 col_offset
屬性的節(jié)點(diǎn)。)
新增函數(shù) ast.get_source_segment()
返回指定 AST 節(jié)點(diǎn)的源代碼。
(由 Ivan Levkivskyi 在 bpo-33416 中貢獻(xiàn)。)
ast.parse()
函數(shù)具有一些新的旗標(biāo):
type_comments=True
導(dǎo)致其返回與特定 AST 節(jié)點(diǎn)相關(guān)聯(lián)的 PEP 484 和 PEP 526 類型注釋文本;mode='func_type'
可被用于解析 PEP 484 "簽名類型注釋" (為函數(shù)定義 AST 節(jié)點(diǎn)而返回);feature_version=(3, N)
允許指定一個(gè)更早的 Python 3 版本。 例如,feature_version=(3, 4)
將把async
和await
視為非保留字。
(由 Guido van Rossum 在 bpo-35766 中貢獻(xiàn)。)
asyncio?
asyncio.run()
已經(jīng)從暫定狀態(tài)晉級(jí)為穩(wěn)定 API。 此函數(shù)可被用于執(zhí)行一個(gè) coroutine 并返回結(jié)果,同時(shí)自動(dòng)管理事件循環(huán)。 例如:
import asyncio
async def main():
await asyncio.sleep(0)
return 42
asyncio.run(main())
這 大致 等價(jià)于:
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()
實(shí)際的實(shí)現(xiàn)要更復(fù)雜許多。 因此 asyncio.run()
應(yīng)該作為運(yùn)行 asyncio 程序的首選方式。
(由 Yury Selivanov 在 bpo-32314 中貢獻(xiàn)。)
運(yùn)行 python -m asyncio
將啟動(dòng)一個(gè)原生異步 REPL。 這允許快速體驗(yàn)具有最高層級(jí) await
的代碼。 這時(shí)不再需要直接調(diào)用 asyncio.run()
,因?yàn)榇瞬僮鲿?huì)在每次發(fā)起調(diào)用時(shí)產(chǎn)生一個(gè)新事件循環(huán):
$ 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 中貢獻(xiàn)。)
異常 asyncio.CancelledError
現(xiàn)在繼承自 BaseException
而不是 Exception
并且不再繼承自 concurrent.futures.CancelledError
。 (由 Yury Selivanov 在 bpo-32528 中貢獻(xiàn)。)
在 Windows 上,現(xiàn)在默認(rèn)的事件循環(huán)為 ProactorEventLoop
。 (由 Victor Stinner 在 bpo-34687 中貢獻(xiàn)。)
ProactorEventLoop
現(xiàn)在也支持 UDP。 (由 Adam Meily 和 Andrew Svetlov 在 bpo-29883 中貢獻(xiàn)。)
ProactorEventLoop
現(xiàn)在可通過 KeyboardInterrupt
("CTRL+C") 來中斷。 (由 Vladimir Matveev 在 bpo-23057 中貢獻(xiàn)。)
添加了 asyncio.Task.get_coro()
用來獲取 asyncio.Task
中的已包裝協(xié)程。 (由 Alex Gr?nholm 在 bpo-36999 中貢獻(xiàn)。)
asyncio 任務(wù)現(xiàn)在可以被命名,或者是通過將 name
關(guān)鍵字參數(shù)傳給 asyncio.create_task()
或 create_task()
事件循環(huán)方法,或者是通過在任務(wù)對(duì)象上調(diào)用 set_name()
方法。 任務(wù)名稱在 asyncio.Task
的 repr()
輸出中可見,并且還可以使用 get_name()
方法來獲取。 (由 Alex Gr?nholm 在 bpo-34270 中貢獻(xiàn)。)
將對(duì) Happy Eyeballs 的支持添加到 asyncio.loop.create_connection()
。 要指定此行為,已增加了兩個(gè)新的形參: happy_eyeballs_delay 和 interleave。 Happy Eyeballs 算法可提升支持 IPv4 和 IPv6 的應(yīng)用的響應(yīng)速度,具體做法是嘗試同時(shí)使用兩者進(jìn)行連接。 (由 twisteroid ambassador 在 bpo-33530 中貢獻(xiàn)。)
builtins?
內(nèi)置的 compile()
已改進(jìn)為可接受 ast.PyCF_ALLOW_TOP_LEVEL_AWAIT
旗標(biāo)。 當(dāng)傳入此新旗標(biāo)時(shí),compile()
將允許通常被視為無效語法的最高層級(jí) await
, async for
和 async with
構(gòu)造。 此后將可返回帶有 CO_COROUTINE
旗標(biāo)的異步代碼對(duì)象。 (由 Matthias Bussonnier 在 bpo-34616 中貢獻(xiàn)。)
collections?
collections.namedtuple()
的 _asdict()
方法現(xiàn)在將返回 dict
而不是 collections.OrderedDict
。 此項(xiàng)更改是由于普通字典自 Python 3.7 起已保證具有確定的元素順序。 如果還需要 OrderedDict
的額外特性,建議的解決方案是將結(jié)果轉(zhuǎn)換為需要的類型: OrderedDict(nt._asdict())
。 (由 Raymond Hettinger 在 bpo-35864 中貢獻(xiàn)。)
cProfile?
cProfile.Profile
類現(xiàn)在可被用作上下文管理器。 在運(yùn)行時(shí)對(duì)一個(gè)代碼塊實(shí)現(xiàn)性能分析:
import cProfile
with cProfile.Profile() as profiler:
# code to be profiled
...
(由 Scott Sanderson 在 bpo-29235 中貢獻(xiàn)。)
csv?
csv.DictReader
現(xiàn)在將返回 dict
而不是 collections.OrderedDict
。 此工具現(xiàn)在會(huì)更快速且消耗更少內(nèi)存同時(shí)仍然保留字段順序。 (由 Michael Selik 在 bpo-34003 中貢獻(xiàn)。)
curses?
添加了一個(gè)新變量用于保存下層 ncurses 庫(kù)的結(jié)構(gòu)版信息: ncurses_version
。 (由 Serhiy Storchaka 在 bpo-31680 中貢獻(xiàn)。)
ctypes?
在 Windows 上,CDLL
及其子類現(xiàn)在接受 winmode 形參來指定用于底層 LoadLibraryEx
調(diào)用的旗標(biāo)。 默認(rèn)旗標(biāo)被設(shè)為僅加載來自可信任位置的 DLL 依賴項(xiàng),包括 DLL 的存放路徑(如果加載初始 DLL 時(shí)使用了完整或部分路徑)以及通過 add_dll_directory()
添加的路徑。 (由 Steve Dower 在 bpo-36085 中貢獻(xiàn)。)
datetime?
添加了新的替代構(gòu)造器 datetime.date.fromisocalendar()
和 datetime.datetime.fromisocalendar()
,它們分別基于 ISO 年份、周序號(hào)和周內(nèi)日序號(hào)來構(gòu)造 date
和 datetime
對(duì)象;這兩者分別是其所對(duì)應(yīng)類中 isocalendar
方法的逆操作。 (由 Paul Ganssle 在 bpo-36004 中貢獻(xiàn)。)
functools?
functools.lru_cache()
現(xiàn)在可直接作為裝飾器而不是作為返回裝飾器的函數(shù)。 因此這兩種寫法現(xiàn)在都被支持:
@lru_cache
def f(x):
...
@lru_cache(maxsize=256)
def f(x):
...
(由 Raymond Hettinger 在 bpo-36772 中貢獻(xiàn)。)
添加了新的 functools.cached_property()
裝飾器,用于在實(shí)例生命周期內(nèi)緩存的已計(jì)算特征屬性。
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 中貢獻(xiàn))
添加了新的 functools.singledispatchmethod()
裝飾器可使用 single dispatch 將方法轉(zhuǎn)換為 泛型函數(shù):
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 中貢獻(xiàn))
gc?
get_objects()
現(xiàn)在能接受一個(gè)可選的 generation 形參來指定一個(gè)用于獲取對(duì)象的生成器。 (由 Pablo Galindo 在 bpo-36016 中貢獻(xiàn)。)
gettext?
添加了 pgettext()
及其變化形式。 (由 Franz Glasner, éric Araujo 和 Cheryl Sabella 在 bpo-2504 中貢獻(xiàn)。)
gzip?
添加 mtime 形參到 gzip.compress()
用于可重現(xiàn)的輸出。 (由 Guo Ci Teo 在 bpo-34898 中貢獻(xiàn)。)
對(duì)于特定類型的無效或已損壞 gzip 文件現(xiàn)在將引發(fā) BadGzipFile
而不是 OSError
。 (由 Filip Gruszczyński, Michele Orrù 和 Zackery Spytz 在 bpo-6584 中貢獻(xiàn)。)
IDLE 與 idlelib?
超過 N 行(默認(rèn)值為 50)的輸出將被折疊為一個(gè)按鈕。 N 可以在 Settings 對(duì)話框的 General 頁的 PyShell 部分中進(jìn)行修改。 數(shù)量較少但是超長(zhǎng)的行可以通過在輸出上右擊來折疊。 被折疊的輸出可通過雙擊按鈕來展開,或是通過右擊按鈕來放入剪貼板或是單獨(dú)的窗口。 (由 Tal Einat 在 bpo-1529353 中貢獻(xiàn)。)
在 Run 菜單中增加了 "Run Customized" 以使用自定義設(shè)置來運(yùn)行模塊。 輸入的任何命令行參數(shù)都會(huì)被加入 sys.argv。 它們?cè)谙麓巫远x運(yùn)行時(shí)會(huì)再次顯示在窗體中。 用戶也可以禁用通常的 Shell 主模塊重啟。 (由 Cheryl Sabella, Terry Jan Reedy 等人在 bpo-5680 和 bpo-37627 中貢獻(xiàn)。)
在 IDLE 編輯器窗口中增加了可選的行號(hào)。 窗口打開時(shí)默認(rèn)不顯示行號(hào),除非在配置對(duì)話框的 General 選項(xiàng)卡中特別設(shè)置。 已打開窗口中的行號(hào)可以在 Options 菜單中顯示和隱藏。 (由 Tal Einat 和 Saimadhav Heblikar 在 bpo-17535 中貢獻(xiàn)。)
現(xiàn)在會(huì)使用 OS 本機(jī)編碼格式在 Python 字符串和 Tcl 對(duì)象間進(jìn)行轉(zhuǎn)換。 這允許在 IDLE 中處理 emoji 和其他非 BMP 字符。 這些字符將可被顯示或是從剪貼板復(fù)制和粘貼。 字符串從 Tcl 到 Python 的來回轉(zhuǎn)換現(xiàn)在不會(huì)再發(fā)生失敗。 (過去八年有許多人都為此付出過努力,問題最終由 Serhiy Storchaka 在 bpo-13153 中解決。)
在 3.8.1 中新增:
添加切換光標(biāo)閃爍停止的選項(xiàng)。 (由 Zackery Spytz 在 bpo-4603 中貢獻(xiàn)。)
Esc 鍵現(xiàn)在會(huì)關(guān)閉 IDLE 補(bǔ)全提示窗口。 (由 Johnny Najera 在 bpo-38944 中貢獻(xiàn)。)
上述修改已被反向移植到 3.7 維護(hù)發(fā)行版中。
添加關(guān)鍵字到模塊名稱補(bǔ)全列表。 (由 Terry J. Reedy 在 bpo-37765 中貢獻(xiàn)。)
inspect?
inspect.getdoc()
函數(shù)現(xiàn)在可以找到 __slots__
的文檔字符串,如果該屬性是一個(gè)元素值為文檔字符串的 dict
的話。 這提供了類似于目前已有的 property()
, classmethod()
和 staticmethod()
等函數(shù)的文檔選項(xiàng):
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 中貢獻(xiàn)。)
io?
在開發(fā)模式 (-X
env
) 和 調(diào)試編譯版 中,io.IOBase
終結(jié)器現(xiàn)在會(huì)在 close()
方法失敗時(shí)將異常寫入日志。 發(fā)生的異常在發(fā)布編譯版中會(huì)被靜默地忽略。 (由 Victor Stinner 在 bpo-18748 中貢獻(xiàn)。)
itertools?
itertools.accumulate()
函數(shù)增加了可選的 initial 關(guān)鍵字參數(shù)用來指定一個(gè)初始值:
>>> from itertools import accumulate
>>> list(accumulate([10, 5, 30, 15], initial=1000))
[1000, 1010, 1015, 1045, 1060]
(由 Lisa Roach 在 bpo-34659 中貢獻(xiàn)。)
json.tool?
添加選項(xiàng) --json-lines
用于將每個(gè)輸入行解析為單獨(dú)的 JSON 對(duì)象。 (由 Weipeng Hong 在 bpo-31553 中貢獻(xiàn)。)
logging?
為 logging.basicConfig()
添加了 force 關(guān)鍵字參數(shù),當(dāng)設(shè)為真值時(shí),關(guān)聯(lián)到根日志記錄器的任何現(xiàn)有處理程序都將在執(zhí)行由其他參數(shù)所指定的配置之前被移除并關(guān)閉。
這解決了一個(gè)長(zhǎng)期存在的問題。 當(dāng)一個(gè)日志處理器或 basicConfig() 被調(diào)用時(shí),對(duì) basicConfig() 的后續(xù)調(diào)用會(huì)被靜默地忽略。 這導(dǎo)致使用交互提示符或 Jupyter 筆記本更新、試驗(yàn)或講解各種日志配置選項(xiàng)變得相當(dāng)困難。
(由 Raymond Hettinger 提議,由 Dong-hee Na 實(shí)現(xiàn),并由 Vinay Sajip 在 bpo-33897 中完成審核。)
math?
添加了新的函數(shù) math.dist()
用于計(jì)算兩點(diǎn)之間的歐幾里得距離。 (由 Raymond Hettinger 在 bpo-33089 中貢獻(xiàn)。)
擴(kuò)展了 math.hypot()
函數(shù)以便處理更多的維度。 之前它僅支持 2-D 的情況。 (由 Raymond Hettinger 在 bpo-33089 中貢獻(xiàn)。)
添加了新的函數(shù) math.prod()
作為的 sum()
同類,該函數(shù)返回 'start' 值 (默認(rèn)值: 1) 乘以一個(gè)數(shù)字可迭代對(duì)象的積:
>>> prior = 0.8
>>> likelihoods = [0.625, 0.84, 0.30]
>>> math.prod(likelihoods, start=prior)
0.126
(由 Pablo Galindo 在 bpo-35606 中貢獻(xiàn)。)
添加了兩個(gè)新的組合函數(shù) 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-37128, bpo-37178 和 bpo-35431 中貢獻(xiàn)。)
添加了一個(gè)新函數(shù) math.isqrt()
用于計(jì)算精確整數(shù)平方根而無需轉(zhuǎn)換為浮點(diǎn)數(shù)。 該新函數(shù)支持任意大整數(shù)。 它的執(zhí)行速度比 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 中貢獻(xiàn)。)
函數(shù) math.factorial()
不再接受非整數(shù)類參數(shù)。 (由 Pablo Galindo 在 bpo-33083 中貢獻(xiàn)。)
mmap?
mmap.mmap
類現(xiàn)在具有一個(gè) madvise()
方法用于訪問 madvise()
系統(tǒng)調(diào)用。 (由 Zackery Spytz 在 bpo-32941 中貢獻(xiàn)。)
multiprocessing?
添加了新的 multiprocessing.shared_memory
模塊。 (由 Davin Potts 在 bpo-35813 中貢獻(xiàn)。)
在macOS上,現(xiàn)在默認(rèn)使用的啟動(dòng)方式是*spawn*啟動(dòng)方式。 (由 Victor Stinner 在 bpo-33725 中貢獻(xiàn)。)
os?
在 Windows 上添加了新函數(shù) add_dll_directory()
用于在導(dǎo)入擴(kuò)展模塊或使用 ctypes
加載 DLL 時(shí)為本機(jī)依賴提供額外搜索路徑 。 (由 Steve Dower 在 bpo-36085 中貢獻(xiàn)。)
添加了新的 os.memfd_create()
函數(shù)用于包裝 memfd_create()
系統(tǒng)調(diào)用。 (由 Zackery Spytz 和 Christian Heimes 在 bpo-26836 中貢獻(xiàn)。)
在 Windows 上,大部分用于處理重解析點(diǎn),(包括符號(hào)鏈接和目錄連接)的手動(dòng)邏輯已被委托給操作系統(tǒng)。 特別地,os.stat()
現(xiàn)在將會(huì)遍歷操作系統(tǒng)所支持的任何內(nèi)容,而 os.lstat()
將只打開被標(biāo)識(shí)為“名稱代理”的重解析點(diǎn),而其要由 os.stat()
打開其他的重解析點(diǎn)。 在所有情況下,stat_result.st_mode
將只為符號(hào)鏈接而非其他種類的重解析點(diǎn)設(shè)置 S_IFLNK
。 要標(biāo)識(shí)其他種類的重解析點(diǎn),請(qǐng)檢查新的 stat_result.st_reparse_tag
屬性。
在 Windows 上,os.readlink()
現(xiàn)在能夠讀取目錄連接。 請(qǐng)注意 islink()
會(huì)對(duì)目錄連接返回 False
,因此首先檢查 islink
的代碼將連續(xù)把連接視為目錄,而會(huì)處理 os.readlink()
所引發(fā)錯(cuò)誤的代碼現(xiàn)在會(huì)把連接視為鏈接。
(由 Steve Dower 在 bpo-37834 中貢獻(xiàn)。)
os.path?
返回布爾值結(jié)果的 os.path
函數(shù)例如 exists()
, lexists()
, isdir()
, isfile()
, islink()
, 以及 ismount()
現(xiàn)在對(duì)于包含在 OS 層級(jí)無法表示的字符或字節(jié)的路徑將會(huì)返回 False
而不是引發(fā) ValueError
或其子類 UnicodeEncodeError
和 UnicodeDecodeError
。 (由 Serhiy Storchaka 在 bpo-33721 中貢獻(xiàn)。)
expanduser()
在 Windows 上現(xiàn)在改用 USERPROFILE
環(huán)境變量而不再使用 HOME
,后者通常不會(huì)為一般用戶賬戶設(shè)置。 (由 Anthony Sottile 在 bpo-36264 中貢獻(xiàn)。)
isdir()
在 Windows 上將不再為不存在的目錄的鏈接返回 True
。
realpath()
在 Windows 上現(xiàn)在會(huì)識(shí)別重解析點(diǎn),包括符號(hào)鏈接和目錄連接。
(由 Steve Dower 在 bpo-37834 中貢獻(xiàn)。)
pathlib?
返回布爾值結(jié)果的 pathlib.Path
方法例如 exists()
, is_dir()
, is_file()
, is_mount()
, is_symlink()
, is_block_device()
, is_char_device()
, is_fifo()
, is_socket()
現(xiàn)在對(duì)于包含在 OS 層級(jí)無法表示的字符或字節(jié)的路徑將會(huì)返回 False
而不是引發(fā) ValueError
或其子類 UnicodeEncodeError
。 (由 Serhiy Storchaka 在 bpo-33721 中貢獻(xiàn)。)
Added pathlib.Path.link_to()
which creates a hard link pointing
to a path.
(Contributed by Joannah Nanjekye in bpo-26978)
Note that link_to
was deprecated in 3.10 and removed in 3.12 in
favor of a hardlink_to
method added in 3.10 which matches the
semantics of the existing symlink_to
method.
pickle?
pickle
擴(kuò)展子類化針對(duì) C 優(yōu)化的 Pickler
現(xiàn)在可通過定義特殊的 reducer_override()
方法來重載函數(shù)和類的封存邏輯。 (由 Pierre Glaser 和 Olivier Grisel 在 bpo-35900 中貢獻(xiàn)。)
plistlib?
添加了新的 plistlib.UID
并啟動(dòng)了對(duì)讀取和寫入經(jīng)過 NSKeyedArchiver 編碼的二進(jìn)制 plists 的支持。 (由 Jon Janzen 在 bpo-26707 中貢獻(xiàn)。)
pprint?
pprint
模塊為一些函數(shù)添加了 sort_dicts 形參。 默認(rèn)情況下,這些函數(shù)會(huì)繼續(xù)在渲染或打印之前對(duì)字典進(jìn)行排序。 但是,如果 sort_dicts 設(shè)為假值,則字典將保持鍵插入時(shí)的順序。 這在調(diào)試期間與 JSON 輸入進(jìn)行比較時(shí)會(huì)很有用。
除此之外,還增加了一個(gè)方便的新函數(shù) pprint.pp()
,它類似于 pprint.pprint()
但它的 sort_dicts 默認(rèn)為 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 中貢獻(xiàn)。)
py_compile?
py_compile.compile()
現(xiàn)在支持靜默模式。 (由 Joannah Nanjekye 在 bpo-22640 中貢獻(xiàn)。)
shlex?
新增了 shlex.join()
函數(shù)作為 shlex.split()
的逆操作。 (由 Bo Bayles 在 bpo-32102 中貢獻(xiàn)。)
shutil?
shutil.copytree()
現(xiàn)在接受新的 dirs_exist_ok
關(guān)鍵字參數(shù)。 (由 Josh Bronson 在 bpo-20849 中貢獻(xiàn)。)
shutil.make_archive()
現(xiàn)在對(duì)新的歸檔默認(rèn)使用 modern pax (POSIX.1-2001) 格式以提升可移植性和標(biāo)準(zhǔn)一致性,此特性繼承自對(duì) tarfile
模塊的相應(yīng)更改。 (由 C.A.M. Gerlach 在 bpo-30661 中貢獻(xiàn)。)
shutil.rmtree()
在 Windows 上現(xiàn)在會(huì)移除目錄連接而不會(huì)遞歸地先移除其中的內(nèi)容。 (由 Steve Dower 在 bpo-37834 中貢獻(xiàn)。)
socket?
添加了便捷的 create_server()
和 has_dualstack_ipv6()
函數(shù)以自動(dòng)化在創(chuàng)建服務(wù)器套接字時(shí)通常情況下所必須的任務(wù),包括在同一套接字中同時(shí)接受 IPv4 和 IPv6 連接。 (由 Giampaolo Rodolà 在 bpo-17561 中貢獻(xiàn)。)
socket.if_nameindex()
, socket.if_nametoindex()
和 socket.if_indextoname()
函數(shù)已經(jīng)在 Windows 上實(shí)現(xiàn)。 (由 Zackery Spytz 在 bpo-37007 中貢獻(xiàn)。)
ssl?
增加了 post_handshake_auth
和 verify_client_post_handshake()
分別啟用和初始化 TLS 1.3 握手后驗(yàn)證。 (由 Christian Heimes 在 bpo-34670 中貢獻(xiàn)。)
statistics?
添加了 statistics.fmean()
作為 statistics.mean()
的更快速的浮點(diǎn)數(shù)版版本。 (由 Raymond Hettinger 和 Steven D'Aprano 在 bpo-35904 中貢獻(xiàn)。)
添加了 statistics.geometric_mean()
(由 Raymond Hettinger 在 bpo-27181 中貢獻(xiàn)。)
添加了 statistics.multimode()
用于返回最常見值的列表。 (由 Raymond Hettinger 在 bpo-35892 中貢獻(xiàn)。)
添加了 statistics.quantiles()
用于將數(shù)據(jù)或分布劃分為多個(gè)等概率區(qū)間(例如四分位、十分位或百分位)。 (由 Raymond Hettinger 在 bpo-36546 中貢獻(xiàn)。)
添加了 statistics.NormalDist
用于創(chuàng)建和操縱隨機(jī)變量的正態(tài)分布。 (由 Raymond Hettinger 在 bpo-36018 中貢獻(xiàn)。)
>>> 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()
函數(shù),可被重載以便控制如何處理“不可引發(fā)的異?!?。 它會(huì)在發(fā)生了一個(gè)異常但 Python 沒有辦法處理時(shí)被調(diào)用。 例如,當(dāng)一個(gè)析構(gòu)器在垃圾回收時(shí) (gc.collect()
) 所引發(fā)的異常。 (由 Victor Stinner 在 bpo-36829 中貢獻(xiàn)。)
tarfile?
tarfile
模塊現(xiàn)在對(duì)新的歸檔默認(rèn)使用 modern pax (POSIX.1-2001) 格式而不再是之前的 GNU 專屬格式。 這通過標(biāo)準(zhǔn)化和可擴(kuò)展格式的統(tǒng)一編碼 (UTF-8) 提升了跨平臺(tái)可移植性,還提供了其他一些益處。 (由 C.A.M. Gerlach 在 bpo-36268 中貢獻(xiàn)。)
threading?
添加了新的 threading.excepthook()
函數(shù)用來處理未捕獲的 threading.Thread.run()
異常。 它可被重載以便控制如何處理未捕獲的 threading.Thread.run()
異常。 (由 Victor Stinner 在 bpo-1230540 中貢獻(xiàn)。)
添加了新的 threading.get_native_id()
函數(shù)以及 threading.Thread
類的 native_id
屬性。 它們會(huì)返回內(nèi)核所分配給當(dāng)前線程的原生整數(shù)線程 ID。 此特性僅在特定平臺(tái)上可用,參見 get_native_id
了解詳情。 (由 Jake Tesler 在 bpo-36084 中貢獻(xiàn)。)
tokenize?
當(dāng)提供不帶末尾新行的輸入時(shí),tokenize
模塊現(xiàn)在會(huì)隱式地添加 NEWLINE
形符。 此行為現(xiàn)在已與 C 詞法分析器的內(nèi)部行為相匹配。 (由 Ammar Askar 在 bpo-33899 中貢獻(xiàn)。)
tkinter?
在 tkinter.Spinbox
中添加了方法 selection_from()
, selection_present()
, selection_range()
和 selection_to()
。 (由 Juliette Monsel 在 bpo-34829 中貢獻(xiàn)。)
在 tkinter.Canvas
類中添加了方法 moveto()
。 (由 Juliette Monsel 在 bpo-23831 中貢獻(xiàn)。)
tkinter.PhotoImage
類現(xiàn)在具有 transparency_get()
和 transparency_set()
方法。 (由 Zackery Spytz 在 bpo-25451 中貢獻(xiàn)。)
time?
為 macOS 10.12 添加了新的時(shí)鐘 CLOCK_UPTIME_RAW
。 (由 Joannah Nanjekye 在 bpo-35702 中貢獻(xiàn)。)
typing?
typing
模塊加入了一些新特性:
一個(gè)帶有鍵專屬類型的字典類型。 參見 PEP 589 和
typing.TypedDict
。 TypedDict 只使用字符串作為鍵。 默認(rèn)情況下每個(gè)鍵都要求提供。 指定 "total=False" 以允許鍵作為可選項(xiàng):class Location(TypedDict, total=False): lat_long: tuple grid_square: str xy_coordinate: tuple
Literal 類型。 參見 PEP 586 和
typing.Literal
。 Literal 類型指明一個(gè)形參或返回值被限定為一個(gè)或多個(gè)特定的字面值:def get_status(port: int) -> Literal['connected', 'disconnected']: ...
"Final" 變量、函數(shù)、方法和類。 參見 PEP 591,
typing.Final
和typing.final()
。 final 限定符會(huì)指示靜態(tài)類型檢查器限制進(jìn)行子類化、重載或重新賦值:pi: Final[float] = 3.1415926536
協(xié)議定義。 參見 PEP 544,
typing.Protocol
和typing.runtime_checkable()
。 簡(jiǎn)單的 ABC 例如typing.SupportsInt
現(xiàn)在是Protocol
的子類。新的協(xié)議類
typing.SupportsIndex
。新的函數(shù)
typing.get_origin()
和typing.get_args()
。
unicodedata?
unicodedata
模塊現(xiàn)在已升級(jí)為使用 Unicode 12.1.0 發(fā)布版。
新的函數(shù) is_normalized()
可被用來驗(yàn)證字符串是否為特定正規(guī)形式,通常會(huì)比實(shí)際進(jìn)行字符串正規(guī)化要快得多。 (由 Max Belanger, David Euresti 和 Greg Price 在 bpo-32285 和 bpo-37966 中貢獻(xiàn)。)
unittest?
添加了 AsyncMock
以支持異步版本的 Mock
。 同時(shí)也添加了相應(yīng)的斷言函數(shù)用于測(cè)試。 (由 Lisa Roach 在 bpo-26467 中貢獻(xiàn)。)
unittest 添加了 addModuleCleanup()
和 addClassCleanup()
以支持對(duì) setUpModule()
和 setUpClass()
進(jìn)行清理。 (由 Lisa Roach 在 bpo-24412 中貢獻(xiàn)。)
一些模擬斷言函數(shù)現(xiàn)在也會(huì)在失敗時(shí)打印一個(gè)實(shí)際調(diào)用列表。 (由 Petter Strandmark 在 bpo-35047 中貢獻(xiàn)。)
unittest
模塊已支持通過 unittest.IsolatedAsyncioTestCase
來使用協(xié)程作為測(cè)試用例。 (由 Andrew Svetlov 在 bpo-32972 中貢獻(xiàn)。)
示例:
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?
現(xiàn)在 venv
在所有平臺(tái)上都會(huì)包含 Activate.ps1
腳本用于在 PowerShell Core 6.1 下激活虛擬環(huán)境。 (由 Brett Cannon 在 bpo-32718 中貢獻(xiàn)。)
weakref?
由 weakref.proxy()
返回的代理對(duì)象現(xiàn)在除其他算術(shù)運(yùn)算符外也支持矩陣乘法運(yùn)算符 @
和 @=
。 (由 Mark Dickinson 在 bpo-36669 中貢獻(xiàn)。)
xml?
作為對(duì) DTD 和外部實(shí)體檢索的緩解,在默認(rèn)情況下 xml.dom.minidom
和 xml.sax
模塊不再處理外部實(shí)體。 (由 Christian Heimes 在 bpo-17239 中貢獻(xiàn)。)
xml.etree.ElementTree
模塊中的 .find*()
方法支持通配符搜索例如 {*}tag
,此搜索會(huì)忽略命名空間以及返回給定命名空間中所有標(biāo)簽的 {namespace}*
。 (由 Stefan Behnel 在 bpo-28238 中貢獻(xiàn)。)
xml.etree.ElementTree
模塊提供了實(shí)現(xiàn) C14N 2.0 的新函數(shù) –xml.etree.ElementTree.canonicalize()
。 (由 Stefan Behnel 在 bpo-13611 中貢獻(xiàn)。)
xml.etree.ElementTree.XMLParser
的目標(biāo)對(duì)象可通過新的回調(diào)方法 start_ns()
和 end_ns()
來接受命名空間聲明事件。 此外,xml.etree.ElementTree.TreeBuilder
目標(biāo)可被配置為處理有關(guān)注釋和處理指令事件以將它們包含在所生成的樹當(dāng)中。 (由 Stefan Behnel 在 bpo-36676 和 bpo-36673 中貢獻(xiàn)。)
xmlrpc?
xmlrpc.client.ServerProxy
現(xiàn)在支持可選的 headers 關(guān)鍵字參數(shù)作為隨同每次請(qǐng)求發(fā)送的 HTTP 標(biāo)頭序列。 此特征的作用之一是使得從默認(rèn)的基礎(chǔ)認(rèn)證升級(jí)到更快速的會(huì)話認(rèn)證成為可能。 (由 Cédric Krier 在 bpo-35153 中貢獻(xiàn)。)
性能優(yōu)化?
subprocess
模塊現(xiàn)在能在某些情況下使用os.posix_spawn()
函數(shù)以獲得更好的性能。 目前,它的使用僅限 macOS 和 Linux(使用 glibc 2.24 或更新版本),并要求滿足以下條件:close_fds 為假值;
preexec_fn, pass_fds, cwd 和 start_new_session 形參未設(shè)置;
executable 路徑包含一個(gè)目錄。
(由 Joannah Nanjekye 和 Victor Stinner 在 bpo-35537 中貢獻(xiàn)。)
shutil.copyfile()
,shutil.copy()
,shutil.copy2()
,shutil.copytree()
和shutil.move()
在 Linux 和 macOS 上會(huì)使用平臺(tái)專屬的 "fast-copy" 系統(tǒng)調(diào)用以提高效率。 "fast-copy" 意味著拷貝操作發(fā)生于內(nèi)核中,從而避免在進(jìn)行 "outfd.write(infd.read())
" 等操作時(shí)使用 Python 中的用戶空間緩沖區(qū)。 在 Windows 上shutil.copyfile()
會(huì)使用更大的默認(rèn)緩沖區(qū)(1 MiB 而不是 16 KiB)并且使用基于memoryview()
的shutil.copyfileobj()
版本。 在同一分區(qū)內(nèi)拷貝一個(gè) 512 MiB 文件的速度提升在 Linux 上約為 +26%,在 macOS 上為 +50%,在 Windows 上為 +40%。 此外還將消耗更少的 CPU 周期。 參見 依賴于具體平臺(tái)的高效拷貝操作 一節(jié)。 (由 Giampaolo Rodolà 在 bpo-33671 中貢獻(xiàn)。)shutil.copytree()
會(huì)根據(jù)其所用緩存的os.stat()
值使用os.scandir()
函數(shù)及所有拷貝函數(shù)。 拷貝一個(gè)包含 8000 文件的目錄的速度提升在 Linux 上約為 +9%,在 Windows 上為 +20%,對(duì)于 Windows SMB 共享目錄則為 +30%。 此外os.stat()
系統(tǒng)調(diào)用的次數(shù)也減少了 38%,使得shutil.copytree()
在網(wǎng)絡(luò)文件系統(tǒng)上會(huì)特別快速。 (由Giampaolo Rodolà 在 bpo-33695 中貢獻(xiàn)。)pickle
模塊使用的默認(rèn)協(xié)議現(xiàn)在為 Protocol 4,最早在 Python 3.4 中被引入。 它提供了比自 Python 3.0 起可用的 Protocol 3 更好的性能和更小的數(shù)據(jù)尺寸。Removed one
Py_ssize_t
member fromPyGC_Head
. All GC tracked objects (e.g. tuple, list, dict) size is reduced 4 or 8 bytes. (Contributed by Inada Naoki in bpo-33597.)uuid.UUID
現(xiàn)在會(huì)使用__slots__
以減少內(nèi)存足跡。 (由 Wouter Bolsterlee 和 Tal Einat 在 bpo-30977 中貢獻(xiàn)。)operator.itemgetter()
的性能提升了 33%。 優(yōu)化了參數(shù)處理,并為常見的在元組中單個(gè)非負(fù)整數(shù)索引的情況新增了一條快速路徑(這是標(biāo)準(zhǔn)庫(kù)中的典型用例)。 (由 Raymond Hettinger 在 bpo-35664 中貢獻(xiàn)。加快了在
collections.namedtuple()
中的字段查找。 它們現(xiàn)在的速度快了兩倍以上,成為 Python 中最快的實(shí)例變量查找形式。 (由 Raymond Hettinger, Pablo Galindo 和 Joe Jevnik, Serhiy Storchaka 在 bpo-32492 中貢獻(xiàn)。)如果輸入的可迭代對(duì)象的長(zhǎng)度已知 (即輸入對(duì)象實(shí)現(xiàn)了
__len__
),list
構(gòu)造器不會(huì)過度分配內(nèi)部項(xiàng)緩沖區(qū)。 這使得所創(chuàng)建的列表資源占用平均減少了 12%。 (由 Raymond Hettinger 和 Pablo Galindo 在 bpo-33234 中貢獻(xiàn)。)類變量寫入速度加倍。 當(dāng)一個(gè)非冗余屬性被更新時(shí),之前存在一個(gè)更新 slots 的非必要調(diào)用。 (由 Stefan Behnel, Pablo Galindo Salgado, Raymond Hettinger, Neil Schemenauer, 和 Serhiy Storchaka 在 bpo-36012 中貢獻(xiàn)。)
減少了傳遞給許多內(nèi)置函數(shù)和方法的參數(shù)轉(zhuǎn)換的開銷。 這使得某些簡(jiǎn)單內(nèi)置函數(shù)和方法的速度提升了 20--50%。 (由 Serhiy Storchaka 在 bpo-23867, bpo-35582 和 bpo-36127 中貢獻(xiàn)。)
LOAD_GLOBAL
指令現(xiàn)在會(huì)使用新的 "per opcode cache" 機(jī)制。 它的速度現(xiàn)在提升了大約 40%。 (由 Yury Selivanov 和 Inada Naoki 在 bpo-26219 中貢獻(xiàn)。)
構(gòu)建和 C API 的改變?
默認(rèn)的
sys.abiflags
成為一個(gè)空字符串:pymalloc 的m
旗標(biāo)不再有意義(無論是否啟用 pymalloc 構(gòu)建都是兼容 ABI 的)因此已被移除。 (由 Victor Stinner 在 bpo-36707 中貢獻(xiàn)。)改變的例子:
只會(huì)安裝
python3.8
程序,不再有python3.8m
程序。只會(huì)安裝
python3.8-config
腳本,不再有python3.8m-config
腳本。m
旗標(biāo)已經(jīng)從動(dòng)態(tài)庫(kù)文件名后綴中移除:包括標(biāo)準(zhǔn)庫(kù)中的擴(kuò)展模塊以及第三方包所產(chǎn)生和安裝的模塊例如從 PyPI 下載的模塊。 以 Linux 為例,Python 3.7 的后綴.cpython-37m-x86_64-linux-gnu.so
在 Python 3.8 中改為.cpython-38-x86_64-linux-gnu.so
。
重新組織了所有頭文件以更好地區(qū)分不同種類的 API:
Include/*.h
應(yīng)為可移植的公有穩(wěn)定版 C API。Include/cpython/*.h
應(yīng)為 CPython 專屬的不穩(wěn)定版 C API;公有 API,部分私有 API 附加_Py
or_PY
前綴。Include/internal/*.h
應(yīng)為 CPython 特別專屬的私有內(nèi)部 C API。 此 API 不具備向下兼容保證并且不應(yīng)在 CPython 以外被使用。 它們的公開僅適用于特別限定的需求例如調(diào)試器和性能分析等必須直接訪問 CPython 內(nèi)部數(shù)據(jù)而不通過調(diào)用函數(shù)的應(yīng)用。 此 API 現(xiàn)在是通過make install
安裝的。
(由 Victor Stinner 在 bpo-35134 和 bpo-35081 中貢獻(xiàn),相關(guān)工作由 Eric Snow 在 Python 3.7 中發(fā)起。)
某些宏已被轉(zhuǎn)換為靜態(tài)內(nèi)聯(lián)函數(shù):形參類型和返回類型定義良好,它們不再會(huì)有與宏相關(guān)的問題,變量具有局部作用域。 例如:
PyObject_INIT()
,PyObject_INIT_VAR()
私有函數(shù):
_PyObject_GC_TRACK()
,_PyObject_GC_UNTRACK()
,_Py_Dealloc()
(由 Victor Stinner 在 bpo-35059 中貢獻(xiàn)。)
PyByteArray_Init()
和PyByteArray_Fini()
函數(shù)已被移除。 它們自 Python 2.7.4 和 Python 3.2.0 起就沒有任何用處,被排除在受限 API (穩(wěn)定版 ABI) 之外,并且未被寫入文檔。 (由 Victor Stinner 在 bpo-35713 中貢獻(xiàn)。)PyExceptionClass_Name()
的結(jié)果類型現(xiàn)在是const char *
而非char *
。 (由 Serhiy Storchaka 在 bpo-33818 中貢獻(xiàn)。)Modules/Setup.dist
與Modules/Setup
兩者的共存已被移除。 之前在更新 CPython 源碼樹時(shí),開發(fā)者必須手動(dòng)拷貝Modules/Setup.dist
(在源碼樹內(nèi)) 到Modules/Setup
(在構(gòu)建樹內(nèi)) 以反映上游的任何改變。 舊特性對(duì)打包者來說有一點(diǎn)益處,但代價(jià)是對(duì)追蹤 CPython 開發(fā)進(jìn)程的開發(fā)者造成經(jīng)常性的麻煩,因?yàn)橥浛截愒撐募赡軐?dǎo)致構(gòu)建失敗。現(xiàn)在構(gòu)建系統(tǒng)總是會(huì)從源碼樹內(nèi)的
Modules/Setup
讀取數(shù)據(jù)。 建議希望定制該文件的開發(fā)者在 CPython 的一個(gè) git 分叉或補(bǔ)丁文件中維護(hù)他們的更改,就如他們對(duì)源碼樹做任何其他改變時(shí)一樣。(由 Antoine Pitrou 在 bpo-32430 中貢獻(xiàn)。)
將 Python 數(shù)字轉(zhuǎn)換為 C 整型的函數(shù)例如
PyLong_AsLong()
以及帶有'i'
之類整型轉(zhuǎn)換格式單元的參數(shù)解析函數(shù)例如PyArg_ParseTuple()
現(xiàn)在如果可能將會(huì)使用__index__()
特殊方法而不是__int__()
。 對(duì)于帶有__int__()
方法但沒有__index__()
方法的對(duì)象 (例如Decimal
和Fraction
) 將會(huì)發(fā)出棄用警告。 對(duì)于實(shí)現(xiàn)了__index__()
的對(duì)象PyNumber_Check()
現(xiàn)在將返回1
。PyNumber_Long()
,PyNumber_Float()
和PyFloat_AsDouble()
現(xiàn)在如果可能也將會(huì)使用__index__()
方法。 (由 Serhiy Storchaka 在 bpo-36048 和 bpo-20092 中貢獻(xiàn)。)堆分配類型對(duì)象現(xiàn)在將增加它們?cè)?
PyObject_Init()
(及其對(duì)應(yīng)的宏PyObject_INIT
) 中的引用計(jì)數(shù)而不是在PyType_GenericAlloc()
中。 修改實(shí)例分配或中止分配的類型可能需要進(jìn)行調(diào)整。 (由 Elizondo 在 bpo-35810 中貢獻(xiàn)。)新增函數(shù)
PyCode_NewWithPosOnlyArgs()
允許創(chuàng)建代碼對(duì)象例如PyCode_New()
,但帶有一個(gè)額外的 posonlyargcount 形參以指明僅限位置參數(shù)的數(shù)量。 (由 Pablo Galindo 在 bpo-37221 中貢獻(xiàn)。)Py_SetPath()
現(xiàn)在會(huì)將sys.executable
設(shè)為程序完整路徑 (Py_GetProgramFullPath()
) 而不是程序名稱 (Py_GetProgramName()
)。 (由 Victor Stinner 在 bpo-38234 中貢獻(xiàn)。)
棄用?
distutils 的
bdist_wininst
命令現(xiàn)在已棄用,請(qǐng)改用bdist_wheel
(wheel 包)。 (由 Victor Stinner 在 bpo-37481 中貢獻(xiàn)。)ElementTree
模塊中的已棄用方法getchildren()
和getiterator()
現(xiàn)在會(huì)引發(fā)DeprecationWarning
而不是PendingDeprecationWarning
。 它們將在 Python 3.9 中被移除。 (由 Serhiy Storchaka 在 bpo-29209 中貢獻(xiàn)。)將不是
concurrent.futures.ThreadPoolExecutor
的實(shí)例的對(duì)象傳給loop.set_default_executor()
已被棄用,并將在 Python 3.9 中被禁止。 (由 Elvis Pranskevichus 在 bpo-34075 中貢獻(xiàn)。)xml.dom.pulldom.DOMEventStream
,wsgiref.util.FileWrapper
和fileinput.FileInput
的__getitem__()
方法已被棄用。這些方法的實(shí)現(xiàn)會(huì)忽略它們的 index 形參,并改為返回下一條目。 (由 Berker Peksag 在 bpo-9372 中貢獻(xiàn)。)
typing.NamedTuple
類已棄用了_field_types
屬性而改用具有同樣信息的__annotations__
屬性。 (由 Raymond Hettinger 在 bpo-36320 中貢獻(xiàn)。)ast
類Num
,Str
,Bytes
,NameConstant
和Ellipsis
被視為已棄用并將在未來的 Python 版本中被移除。 應(yīng)當(dāng)改用Constant
。 (由 Serhiy Storchaka 在 bpo-32892 中貢獻(xiàn)。)ast.NodeVisitor
的方法visit_Num()
,visit_Str()
,visit_Bytes()
,visit_NameConstant()
和visit_Ellipsis()
現(xiàn)在已被棄用,并且在未來的 Python 版本中將不再被調(diào)用。 添加visit_Constant()
方法來處理所有常量節(jié)點(diǎn)。 (由 Serhiy Storchaka 在 bpo-36917 中貢獻(xiàn)。)asyncio.coroutine()
decorator 已棄用并將在 3.10 版中被移除。 原有的@asyncio.coroutine
請(qǐng)改用async def
來替代。 (由 Andrew Svetlov 在 bpo-36921 中貢獻(xiàn)。)在
asyncio
中,loop 參數(shù)的顯式傳遞已被棄用并且到 3.10 版時(shí)將會(huì)在以下函數(shù)中被移除:asyncio.sleep()
,asyncio.gather()
,asyncio.shield()
,asyncio.wait_for()
,asyncio.wait()
,asyncio.as_completed()
,asyncio.Task
,asyncio.Lock
,asyncio.Event
,asyncio.Condition
,asyncio.Semaphore
,asyncio.BoundedSemaphore
,asyncio.Queue
,asyncio.create_subprocess_exec()
以及asyncio.create_subprocess_shell()
。將協(xié)程對(duì)象顯式傳遞給
asyncio.wait()
的做法已被棄用并且將在 3.11 版中被移除。 (由 Yury Selivanov 在 bpo-34790 中貢獻(xiàn)。)gettext
模塊中的下列函數(shù)和方法已被棄用:lgettext()
,ldgettext()
,lngettext()
和ldngettext()
。 它們返回已編碼的字節(jié)串,如果轉(zhuǎn)換后的字符串存在編碼問題你將可能遭遇預(yù)期之外的異常。 更好的做法是使用 Python 3 中返回 Unicode 字符串的操作作為替代。 前面的函數(shù)都早已不宜使用。函數(shù)
bind_textdomain_codeset()
,方法output_charset()
和set_output_charset()
,以及函數(shù)translation()
和install()
的 codeset 形參也已被棄用,因?yàn)樗鼈儍H適用于l*gettext()
函數(shù)。 (由 Serhiy Storchaka 在 bpo-33710 中貢獻(xiàn)。)threading.Thread
的isAlive()
方法已棄用。 (由 Dong-hee Na 在 bpo-35283 中貢獻(xiàn)。)許多接受整數(shù)參數(shù)的內(nèi)置和擴(kuò)展模塊的函數(shù)現(xiàn)在將對(duì)傳入
Decimal
,Fraction
以及任何其他可被轉(zhuǎn)換為整數(shù)但會(huì)丟失精度(即具有__int__()
方法但沒有__index__()
方法)的對(duì)象發(fā)出棄用警告。 在未來的版本中則將報(bào)錯(cuò)。 (由 Serhiy Storchaka 在 bpo-36048 中貢獻(xiàn)。)以下參數(shù)作為關(guān)鍵字參數(shù)傳遞的方式已被棄用:
functools.partialmethod()
,weakref.finalize()
,profile.Profile.runcall()
,cProfile.Profile.runcall()
,bdb.Bdb.runcall()
,trace.Trace.runfunc()
與curses.wrapper()
中的 func。unittest.TestCase.addCleanup()
中的 function。concurrent.futures.ThreadPoolExecutor
和concurrent.futures.ProcessPoolExecutor
的submit()
方法中的 fn。contextlib.ExitStack.callback()
,contextlib.AsyncExitStack.callback()
和contextlib.AsyncExitStack.push_async_callback()
中的 callback。multiprocessing.managers.Server
和multiprocessing.managers.SharedMemoryServer
的create()
方法中的 c 和 typeid。weakref.finalize()
中的 obj。
在未來版本的 Python 中,它們將成為 僅限位置參數(shù)。 (由 Serhiy Storchaka 在 bpo-36492 中貢獻(xiàn)。)
API 與特性的移除?
下列特性與 API 已從 Python 3.8 中移除:
自 Python 3.3 起,從
collections
導(dǎo)入 ABC 的做法已棄用,而應(yīng)當(dāng)從collections.abc
執(zhí)行導(dǎo)入。 從 collections 導(dǎo)入的操作在 3.8 中已標(biāo)記為被移除,但將推遲到 3.9 中實(shí)施。 (參見 bpo-36952。)macpath
模塊,在 Python 3.7 中棄用,現(xiàn)已被移除。 (由 Victor Stinner 在 bpo-35471 中貢獻(xiàn)。)函數(shù)
platform.popen()
已被移除,它自 Python 3.3 起就已被棄用:請(qǐng)改用os.popen()
。 (由 Victor Stinner 在 bpo-35345 中貢獻(xiàn)。)函數(shù)
time.clock()
已被移除,它自 Python 3.3 起就已被棄用:請(qǐng)根據(jù)具體需求改用time.perf_counter()
或time.process_time()
以獲得具有良好定義的行為。 (由 Matthias Bussonnier 在 bpo-36895 中貢獻(xiàn)。)pyvenv
腳本已被移除,推薦改用python3.8 -m venv
來幫助消除容易混淆pyvenv
腳本所關(guān)聯(lián)的 Python 解釋器這一問題。 (由 Brett Cannon 在 bpo-25427 中貢獻(xiàn)。)parse_qs
,parse_qsl
和escape
已從cgi
模塊中被移除。 這些函數(shù)自 Python 3.2 或更早就已被棄用。 它們應(yīng)改為從urllib.parse
和html
模塊導(dǎo)入。filemode
函數(shù)已從tarfile
模塊中被移除。 該函數(shù)未被寫入文檔,自 Python 3.3 起就已棄用。XMLParser
構(gòu)造器不再接受 html 參數(shù)。 它從來沒有任何作用并在 Python 3.4 中已被棄用。 所有其他形參現(xiàn)在都是 僅限關(guān)鍵字參數(shù)。 (由 Serhiy Storchaka 在 bpo-29209 中貢獻(xiàn)。)XMLParser
的doctype()
方法已被移除。 (由 Serhiy Storchaka 在 bpo-29209 中貢獻(xiàn)。)"unicode_internal" 編解碼器已被移除。 (由 Inada Naoki 在 bpo-36297 中貢獻(xiàn)。)
sqlite3
模塊的Cache
和Statement
對(duì)象已不再公開給用戶。 (由 Aviv Palivoda 在 bpo-30262 中貢獻(xiàn)。)fileinput.input()
和fileinput.FileInput()
中自 Python 3.6 起就已被忽略并棄用的bufsize
關(guān)鍵字參數(shù)已被移除。 由 Matthias Bussonnier 在 bpo-36952 中貢獻(xiàn)。)在 Python 3.7 中棄用的函數(shù)
sys.set_coroutine_wrapper()
和sys.get_coroutine_wrapper()
已被移除。 (由 Matthias Bussonnier 在 bpo-36933 中貢獻(xiàn)。)
移植到 Python 3.8?
本節(jié)列出了先前描述的更改以及可能需要更改代碼的其他錯(cuò)誤修正.
Python 行為的改變?
yield 表達(dá)式(包括
yield
和yield from
子句)現(xiàn)在不允許在推導(dǎo)式和生成器表達(dá)式中使用(但for
子句最左邊的可迭代對(duì)象表達(dá)式除外)。 (由 Serhiy Storchaka 在 bpo-10544 中貢獻(xiàn)。)當(dāng)標(biāo)識(shí)號(hào)檢測(cè) (
is
和is not
) 與特定類型的字面值 (例如字符串和數(shù)字) 一同使用時(shí)編譯器現(xiàn)在會(huì)產(chǎn)生SyntaxWarning
。 這在 CPython 中通常是可行的,但并不被語言定義所保證。 該警告會(huì)建議用戶改用相等性檢測(cè) (==
and!=
)。 (由 Serhiy Storchaka 在 bpo-34850 中貢獻(xiàn)。)CPython 解釋器在某些情況下可以忽略異常。 在 Python 3.8 中這種情況會(huì)更少發(fā)生。 特別地,從類型字典獲取屬性時(shí)引發(fā)的異常不會(huì)再被忽略。 (由 Serhiy Storchaka 在 bpo-35459 中貢獻(xiàn)。)
從內(nèi)置類型
bool
,int
,float
,complex
和標(biāo)準(zhǔn)庫(kù)的一些類中移除了__str__
實(shí)現(xiàn)。 它們現(xiàn)在會(huì)從object
繼承__str__()
。 作為結(jié)果,在這些類的子類中定義__repr__()
方法將會(huì)影響它們的字符串表示。 (由 Serhiy Storchaka 在 bpo-36793 中貢獻(xiàn)。)在 AIX 上,
sys.platform
將不再包含主要版本號(hào)。 它將總是'aix'
而不再是'aix3'
..'aix7'
。 由于較舊的 Python 版本會(huì)包含該版本號(hào),因此推薦總是使用sys.platform.startswith('aix')
。 (由 M. Felt 在 bpo-36588 中貢獻(xiàn)。)現(xiàn)在
PyEval_AcquireLock()
和PyEval_AcquireThread()
如果當(dāng)解釋器終結(jié)化時(shí)被調(diào)用將會(huì)終結(jié)當(dāng)前線程,以使它們與PyEval_RestoreThread()
,Py_END_ALLOW_THREADS()
以及PyGILState_Ensure()
保持一致。 如果不想要這樣的行為,請(qǐng)通過檢測(cè)_Py_IsFinalizing()
或sys.is_finalizing()
來保護(hù)該調(diào)用。 (由 Joannah Nanjekye 在 bpo-36475 中貢獻(xiàn)。)
Python API 的變化?
在 Windows 上
os.getcwdb()
函數(shù)現(xiàn)在會(huì)使用 UTF-8 編碼格式而不是 ANSI 代碼頁:請(qǐng)參看 PEP 529 了解具體原因。 該函數(shù)在 Windows 上不再被棄用。 (由 Victor Stinner 在 bpo-37412 中貢獻(xiàn)。)現(xiàn)在
subprocess.Popen
在某些情況下會(huì)使用os.posix_spawn()
以獲得更好的性能。 在適用于 Linux 的 Windows 子系統(tǒng)和 QEMU 用戶模擬器上,使用os.posix_spawn()
的Popen
構(gòu)造器不會(huì)再因?yàn)椤罢也坏匠绦颉边@樣的錯(cuò)誤引發(fā)異常。 而是讓子進(jìn)程失敗并返回一個(gè)非零的returncode
。 (由 Joannah Nanjekye 和 Victor Stinner 在 bpo-35537 中貢獻(xiàn)。)The preexec_fn argument of *
subprocess.Popen
is no longer compatible with subinterpreters. The use of the parameter in a subinterpreter now raisesRuntimeError
. (Contributed by Eric Snow in bpo-34651, modified by Christian Heimes in bpo-37951.)imap.IMAP4.logout()
方法不會(huì)再靜默地忽略任意異常。 (由 Victor Stinner 在 bpo-36348 中貢獻(xiàn)。)函數(shù)
platform.popen()
已被移除,它自 Python 3.3 起就已被棄用:請(qǐng)改用os.popen()
。 (由 Victor Stinner 在 bpo-35345 中貢獻(xiàn)。)當(dāng)傳入多模數(shù)據(jù)時(shí)
statistics.mode()
函數(shù)不會(huì)再引發(fā)異常。 它將改為返回在輸入數(shù)據(jù)中遇到的第一個(gè)模式。 (由 Raymond Hettinger 在 bpo-35892 中貢獻(xiàn)。)tkinter.ttk.Treeview
類的selection()
方法不再接受參數(shù)。 帶參數(shù)調(diào)用該方法來改變選擇在 Python 3.6 中已棄用。 請(qǐng)使用專門方法例如selection_set()
來改變選擇。 (由 Serhiy Storchaka 在 bpo-31508 中貢獻(xiàn)。)xml.dom.minidom
的writexml()
,toxml()
和toprettyxml()
方法以及xml.etree
的write()
方法現(xiàn)在會(huì)保留用戶指定的屬性順序。 (由 Diego Rojas 和 Raymond Hettinger 在 bpo-34160 中貢獻(xiàn)。)附帶
'r'
旗標(biāo)打開的dbm.dumb
數(shù)據(jù)庫(kù)現(xiàn)在將是只讀的。 如果數(shù)據(jù)庫(kù)不存在,附帶'r'
和'w'
旗標(biāo)的dbm.dumb.open()
不會(huì)再創(chuàng)建數(shù)據(jù)庫(kù)。 (由 Serhiy Storchaka 在 bpo-32749 中貢獻(xiàn)。)在
XMLParser
的子類中定義的doctype()
方法將不會(huì)再被調(diào)用,并將導(dǎo)致發(fā)出RuntimeWarning
而不是DeprecationWarning
。 請(qǐng)?jiān)谀繕?biāo)上定義doctype()
方法來處理 XML doctype 聲明。 (由 Serhiy Storchaka 在 bpo-29209 中貢獻(xiàn)。)現(xiàn)在當(dāng)自定義元類未在傳給
type.__new__
的命名空間中提供__classcell__
入口時(shí)將引發(fā)RuntimeError
。 在 Python 3.6--3.7 中是則是引發(fā)DeprecationWarning
。 (由 Serhiy Storchaka 在 bpo-23722 中貢獻(xiàn)。)cProfile.Profile
類現(xiàn)在可被用作上下文管理器。 (由 Scott Sanderson 在 bpo-29235 中貢獻(xiàn)。)shutil.copyfile()
,shutil.copy()
,shutil.copy2()
,shutil.copytree()
和shutil.move()
會(huì)使用平臺(tái)專屬的 "fast-copy" 系統(tǒng)調(diào)用(參見 依賴于具體平臺(tái)的高效拷貝操作 一節(jié))。shutil.copyfile()
在 Windows 上的默認(rèn)緩沖區(qū)大小從 16 KiB 改為 1 MiB。PyGC_Head
結(jié)構(gòu)已被完全改變。 所有接觸到該結(jié)構(gòu)的代碼都應(yīng)當(dāng)被重寫。 (參見 bpo-33597。)PyInterpreterState
結(jié)構(gòu)已被移入 "internal" 頭文件(特別是 Include/internal/pycore_pystate.h)。 不透明的PyInterpreterState
作為僅有 API(以及穩(wěn)定版 ABI)的一部分仍然可用。 文檔指明該結(jié)構(gòu)的任何字段都不是公有的,因此我們希望沒人在使用它們。 但是,如果你確實(shí)依賴其中某一個(gè)或更多個(gè)私有字段并且沒有其他替代選項(xiàng),則請(qǐng)開一個(gè) BPO 問題。 我們將盡力幫助你進(jìn)行調(diào)整(可能包括向公有 API 添加訪問器函數(shù))。 (參見 bpo-35886。)現(xiàn)在所有平臺(tái)下的
mmap.flush()
方法都會(huì)在成功時(shí)返回None
并在錯(cuò)誤時(shí)引發(fā)異常。 之前它的行為取決于具體平臺(tái): Windows 下會(huì)在成功時(shí)返回非零值;在失敗時(shí)返回零。 Unix 下會(huì)在成功時(shí)返回零;在失敗時(shí)引發(fā)錯(cuò)誤。 (由 Berker Peksag 在 bpo-2122 中貢獻(xiàn)。)xml.dom.minidom
和xml.sax
模塊默認(rèn)將不再處理外部實(shí)體。 (由 Christian Heimes 在 bpo-17239 中貢獻(xiàn)。)從只讀的
dbm
數(shù)據(jù)庫(kù) (dbm.dumb
,dbm.gnu
或dbm.ndbm
) 刪除鍵將會(huì)引發(fā)error
(dbm.dumb.error
,dbm.gnu.error
或dbm.ndbm.error
) 而不是KeyError
。 (由 Xiang Zhang 在 bpo-33106 中貢獻(xiàn)。)簡(jiǎn)化了字面值的 AST。 所有常量將被表示為
ast.Constant
的實(shí)例。 實(shí)例化舊類Num
,Str
,Bytes
,NameConstant
和Ellipsis
都將返回Constant
的實(shí)例。 (由 Serhiy Storchaka 在 bpo-32892 中貢獻(xiàn)。)expanduser()
在 Windows 上現(xiàn)在改用USERPROFILE
環(huán)境變量而不再使用HOME
,后者通常不會(huì)為一般用戶賬戶設(shè)置。 (由 Anthony Sottile 在 bpo-36264 中貢獻(xiàn)。)異常
asyncio.CancelledError
現(xiàn)在繼承自BaseException
而不是Exception
并且不再繼承自concurrent.futures.CancelledError
。 (由 Yury Selivanov 在 bpo-32528 中貢獻(xiàn)。)當(dāng)使用
asyncio.Task
的實(shí)例時(shí),函數(shù)asyncio.wait_for()
現(xiàn)在會(huì)正確地等待撤銷。 在此之前當(dāng)達(dá)到 timeout 時(shí),它會(huì)被撤銷并立即返回。 (由 Elvis Pranskevichus 在 bpo-32751 中貢獻(xiàn)。)當(dāng)將 'socket' 作為 name 形參傳入時(shí),函數(shù)
asyncio.BaseTransport.get_extra_info()
現(xiàn)在會(huì)返回一個(gè)可安全使用的套接字對(duì)象。 (由 Yury Selivanov 在 bpo-37027 中貢獻(xiàn)。)asyncio.BufferedProtocol
已經(jīng)晉級(jí)為穩(wěn)定 API。
在 Windows 上對(duì)擴(kuò)展模塊的 DLL 依賴以及通過
ctypes
加載的 DLL 的解析現(xiàn)在將更為安全。 只有系統(tǒng)路徑、包含相信 DLL 或 PYD 文件的路徑以及通過add_dll_directory()
添加的目錄才會(huì)被作為加載時(shí)依賴的搜索位置。 特別地,PATH
和當(dāng)前工作目錄將不再被使用,對(duì)它們的修改將不再對(duì)正常的 DLL 解析產(chǎn)生影響。 如果你的應(yīng)用依賴于這些機(jī)制,你應(yīng)當(dāng)先檢查add_dll_directory()
,如果它存在就用它在加載你的庫(kù)時(shí)添加你的 DLL 目錄。 請(qǐng)注意 Windows 7 用戶還需要確保 Windows 更新包 KB2533623 已安裝(這一點(diǎn)也會(huì)由安裝器進(jìn)行驗(yàn)證)。 (由 Steve Dower 在 bpo-36085 中貢獻(xiàn)。)關(guān)聯(lián)到 pgen 的頭文件和函數(shù)在其被純 Python 實(shí)現(xiàn)取代后已被移除。 (由 Pablo Galindo 在 bpo-36623 中貢獻(xiàn)。)
types.CodeType
在構(gòu)造器的第二個(gè)位置新增了一個(gè)形參 (posonlyargcount) 以支持在 PEP 570 中定義的僅限位置參數(shù)。 第一個(gè)參數(shù) (argcount) 現(xiàn)在表示位置參數(shù)的總數(shù)量 (包括僅限位置參數(shù))。types.CodeType
中新增的replace()
方法可用于讓代碼支持 future 特性。
C API 的變化?
PyCompilerFlags
結(jié)構(gòu)體添加了一個(gè)新的 cf_feature_version 字段。 它應(yīng)當(dāng)被初始化為PY_MINOR_VERSION
。 該字段默認(rèn)會(huì)被忽略,當(dāng)且僅當(dāng)PyCF_ONLY_AST
在 cf_flags 中設(shè)置旗標(biāo)時(shí)才會(huì)被使用。 (由 Guido van Rossum 在 bpo-35766 中貢獻(xiàn)。)PyEval_ReInitThreads()
函數(shù)已從 C API 中移除。 它不應(yīng)當(dāng)被顯式地調(diào)用;請(qǐng)改用PyOS_AfterFork_Child()
。 (由 Victor Stinner 在 bpo-36728 中貢獻(xiàn)。)在 Unix 上,C 擴(kuò)展不會(huì)再被鏈接到 libpython,但 Android 和 Cygwin 例外。 當(dāng) Python 被嵌入時(shí),
libpython
不可使用RTLD_LOCAL
加載,而要改用RTLD_GLOBAL
。 之前使用RTLD_LOCAL
已經(jīng)不可能加載未鏈接到libpython
的 C 擴(kuò)展了,例如通過Modules/Setup
的*shared*
部分構(gòu)建的標(biāo)準(zhǔn)庫(kù) C 擴(kuò)展。 (由 Victor Stinner 在 bpo-21536 中貢獻(xiàn)。)在解析或構(gòu)建值時(shí)(例如
PyArg_ParseTuple()
,Py_BuildValue()
,PyObject_CallFunction()
等等)使用形如#
的格式而不定義PY_SSIZE_T_CLEAN
現(xiàn)在將會(huì)引發(fā)DeprecationWarning
。 它將在 3.10 或 4.0 中被移除。 請(qǐng)參閱 解析參數(shù)并構(gòu)建值變量 了解詳情。 (由 Inada Naoki 在 bpo-36381 中貢獻(xiàn)。)堆分配類型的實(shí)例(例如使用
PyType_FromSpec()
創(chuàng)建的實(shí)例)會(huì)保存一個(gè)對(duì)其類型對(duì)象的引用。 提升這些類型對(duì)象引用計(jì)數(shù)的操作已從PyType_GenericAlloc()
移至更低層級(jí)的函數(shù)PyObject_Init()
和PyObject_INIT()
。 這使用通過This makes types created throughPyType_FromSpec()
所創(chuàng)建類型的行為與管理代碼中的其他類保持一致。靜態(tài)分配類型 將不受影響。
在大部分情況下,這應(yīng)該都不會(huì)有附帶影響。 但是,在分配實(shí)例后手動(dòng)提升引用計(jì)數(shù)的類型(也許是為了繞過漏洞)現(xiàn)在可能永遠(yuǎn)不會(huì)被銷毀。 要避免這種情況,這些類需要在實(shí)例撤銷分配期間在類型對(duì)象上調(diào)用 Py_DECREF。
要正確地將這些類型移植到 3.8,請(qǐng)應(yīng)用以下修改:
在分配實(shí)例之后在類型對(duì)象上移除
Py_INCREF
—— 如果有的話。 這可以發(fā)生在調(diào)用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
函數(shù)會(huì)減少類型的引用計(jì)數(shù)。示例:
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 中貢獻(xiàn)。)
Py_DEPRECATED()
宏已經(jīng)針對(duì) MSVC 實(shí)現(xiàn)。 這個(gè)宏現(xiàn)在必須放在符號(hào)名稱之前。示例:
Py_DEPRECATED(3.8) PyAPI_FUNC(int) Py_OldFunction(void);
(由 Zackery Spytz 在 bpo-33407 中貢獻(xiàn)。)
解釋器將不再假裝支持跨發(fā)布版本的擴(kuò)展類型二進(jìn)制兼容性。 由第三方擴(kuò)展模塊所導(dǎo)出的
PyTypeObject
應(yīng)該具有當(dāng)前 Python 版本所要求的所有空位,包括tp_finalize
(Py_TPFLAGS_HAVE_FINALIZE
不會(huì)再在讀取tp_finalize
之前被檢查)。(由 Antoine Pitrou 在 bpo-32388 中貢獻(xiàn)。)
函數(shù)
PyNode_AddChild()
和PyParser_AddToken()
現(xiàn)在接受兩個(gè)額外的int
參數(shù) end_lineno 和 end_col_offset。允許 MinGW 工具直接鏈接到
python38.dll
的libpython38.a
文件已不再包含于標(biāo)準(zhǔn)的 Windows 分發(fā)包中。 如果你需要此文件,可使用gendef
和dlltool
工具來生成它,這些工具是 MinGW binutils 包的一部分:gendef - python38.dll > tmp.def dlltool --dllname python38.dll --def tmp.def --output-lib libpython38.a
已安裝的
pythonXY.dll
所在位置將取決于安裝選項(xiàng)以及 Windows 的版本和語言。 請(qǐng)參閱 在Windows上使用 Python 了解更多信息。 該結(jié)果庫(kù)應(yīng)當(dāng)放在與pythonXY.lib
相同的目錄下,這通常是你的 Python 安裝路徑下的libs
目錄。(由 Steve Dower 在 bpo-37351 中貢獻(xiàn)。)
CPython 字節(jié)碼的改變?
解釋器循環(huán)已通過將塊堆棧展開邏輯移入編譯器獲得了簡(jiǎn)化。 編譯器現(xiàn)在會(huì)發(fā)出顯式指令來調(diào)整值堆棧并為
break
,continue
和return
調(diào)用清除代碼。移除了操作碼
BREAK_LOOP
,CONTINUE_LOOP
,SETUP_LOOP
和SETUP_EXCEPT
。 添加了新的操作碼ROT_FOUR
,BEGIN_FINALLY
,CALL_FINALLY
和POP_FINALLY
。 修改了END_FINALLY
和WITH_CLEANUP_START
的行為。(由 Mark Shannon, Antoine Pitrou 和 Serhiy Storchaka 在 bpo-17611 中貢獻(xiàn)。)
添加了新的操作碼
END_ASYNC_FOR
用于處理當(dāng)?shù)却?async for
循環(huán)的下一項(xiàng)時(shí)引發(fā)的異常。 (由 Serhiy Storchaka 在 bpo-33041 中貢獻(xiàn)。)MAP_ADD
現(xiàn)在會(huì)預(yù)期值為棧的第一個(gè)元素而鍵為第二個(gè)元素。 作出此改變以使得字典推導(dǎo)式能如 PEP 572 所提議的那樣,鍵總是會(huì)在值之前被求值。 (由 J?rn Heissler 在 bpo-35224 中貢獻(xiàn)。)
演示和工具?
添加了一個(gè)檢測(cè)腳本用于對(duì)訪問變量的不同方式進(jìn)行計(jì)時(shí): Tools/scripts/var_access_benchmark.py
。 (由 Raymond Hettinger 在 bpo-35884 中貢獻(xiàn)。)
以下是自 Python 3.3 以來性能提升情況的總結(jié):
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
基準(zhǔn)測(cè)試是在 Intel? Core? i7-4960HQ 處理器 上運(yùn)行從 python.org 獲取的 macOS 64 位版得到的數(shù)據(jù)。 基準(zhǔn)測(cè)試腳本顯示時(shí)間以納秒為單位。
Python 3.8.1 中的重要變化?
出于重要的安全性考量,asyncio.loop.create_datagram_endpoint()
的 reuse_address 形參不再被支持。 這是由 UDP 中的套接字選項(xiàng) SO_REUSEADDR
的行為導(dǎo)致的。 更多細(xì)節(jié)請(qǐng)參閱 loop.create_datagram_endpoint()
的文檔。 (由 Kyle Stanley, Antoine Pitrou 和 Yury Selivanov 在 bpo-37228 中貢獻(xiàn)。。)
Python 3.8.8 中的重要變化?
早先的 Python 版本允許使用 ;
和 &
作為 urllib.parse.parse_qs()
和 urllib.parse.parse_qsl()
中 query 形參的分隔鍵。 出于安全考慮,也為了遵循更新的 W3C 推薦設(shè)置,這已被改為只允許單個(gè)分隔鍵,默認(rèn)為 &
。 這一改變還會(huì)影響 cgi.parse()
和 cgi.parse_multipart()
因?yàn)樗鼈冊(cè)趦?nèi)部使用了受影響的函數(shù)。 要了解更多細(xì)節(jié),請(qǐng)查看它們各自的文檔。 (由 Adam Goldschmidt, Senthil Kumaran 和 Ken Jin 在 bpo-42967 中貢獻(xiàn)。)
Python 3.8.12 中的重要變化?
從 Python 3.8.12 開始 ipaddress
模塊不再接受 IPv4 地址字符串中有任何前綴的零。 前綴的零有歧義且會(huì)被某些庫(kù)解讀為八進(jìn)制數(shù)字。 例如舊版函數(shù) socket.inet_aton()
就將前綴的零視為八進(jìn)制數(shù)字。 最新 inet_pton()
的 glibc 實(shí)現(xiàn)則不接受任何前綴的零。
(最初由 Christian Heimes 在 bpo-36384 中貢獻(xiàn),并由 Achraf Merzouki 向下移植到 3.8。)