本文詳細(xì)介紹 Python 3.8 中的新功能,以及和與 3.7 相比的一些不同點(diǎn)。
新功能
編譯的字節(jié)碼文件的并行文件系統(tǒng)緩存新的 PYTHONPYCACHEPREFIX設(shè)置(也可用 )將隱式字節(jié)碼緩存配置為使用單獨(dú)的并行文件系統(tǒng)樹,而不是每個源目錄中的默認(rèn)子目錄。-X pycache_prefix__pycache_報告緩存的位置sys.pycache_prefix(None表示pycache子目錄中的默認(rèn)位置)。
其他語言變更
一個continue說法是非法finally條款因與實(shí)施問題。在Python 3.8中,這一限制被取消了。
該int類型現(xiàn)在具有as_integer_ratio()與現(xiàn)有float.as_integer_ratio()方法兼容的新方法。
增加了對\N{name}的支持。
Dict和dictviews現(xiàn)在可以使用反向插入順序進(jìn)行迭代 reversed()。
函數(shù)調(diào)用中允許關(guān)鍵字名稱的語法進(jìn)一步受到限制。特別是,f((keyword)=arg)不再允許。它從來沒有打算在關(guān)鍵字參數(shù)賦值術(shù)語的左側(cè)允許多于一個裸名稱。見bpo-34641。
現(xiàn)在允許Iterable解包,而不使用括號yield 和return語句。(由David Cuthbert和Jordan Chapman在bpo-32117中提供。)
不是有效轉(zhuǎn)義序列的反斜杠字符對DeprecationWarning從Python 3.6開始生成。在Python 3.8中它生成了一個SyntaxWarning代替。(由Serhiy Storchaka供稿于bpo-32912。)
SyntaxWarning在某些情況下,編譯器會在元組或列表之前錯過逗號時生成。例如:
1data = [
2 (1, 2, 3) # oops, missing comma!
3 (4, 5, 6)
4]
子類之間的算術(shù)運(yùn)算datetime.date或 datetime.datetime與datetime.timedelta對象現(xiàn)在返回子類的實(shí)例,而不是基類。這也會影響其實(shí)現(xiàn)(直接或間接)使用datetime.timedelta算術(shù)的操作的返回類型,例如 datetime.datetime.astimezone()。
當(dāng)Python解釋器被Ctrl-C(SIGINT)中斷并且KeyboardInterrupt未捕獲到的結(jié)果異常時,Python進(jìn)程現(xiàn)在通過SIGINT信號或正確的退出代碼退出,以便調(diào)用進(jìn)程可以檢測到它因Ctrl而死亡-C。POSIX和Windows上的shell使用它來正確終止交互式會話中的腳本。
改進(jìn)的模塊
現(xiàn)在的_asdict()方法collections.namedtuple()返回一個dict而不是一個collections.OrderedDict。這是有效的,因?yàn)樽訮ython 3.7以來,常規(guī)dicts已經(jīng)保證了排序。如果需要額外的功能OrderedDict,建議的補(bǔ)救措施是將結(jié)果轉(zhuǎn)換為所需的類型:OrderedDict(nt._asdict())。該unicodedata模塊已升級為使用Unicode 12.0.0 版本。
ASYNCIO
在Windows上,現(xiàn)在是默認(rèn)的事件循環(huán)ProactorEventLoop。
gettext
添加pgettext()及其變體。
檢查
如果該屬性是值為docstrings的位置,該inspect.getdoc()函數(shù)現(xiàn)在可以找到文檔字符串。這提供了類似于我們已經(jīng)有文件的選項,以及:__slots__dictproperty()classmethod()staticmethod()
1class AudioClip:
2 slots = {‘bit_rate’: ‘expressed in kilohertz to one decimal place’,
3 ‘duration’: ‘in seconds, rounded up to an integer’}
4 def init(self, bit_rate, duration):
5 self.bit_rate = round(bit_rate / 1000.0, 1)
6 self.duration = ceil(duration)
GC
get_objects()現(xiàn)在可以接收一個可選的生成參數(shù),指示從中獲取對象的生成。由Pablo Galindo 提供的 bpo-36016。
gzip
添加了mtime參數(shù)以gzip.compress()獲得可重現(xiàn)的輸出。(由Guo Ci Teo在bpo-34898供稿。)
idlelib和IDLE
超過N行的輸出(默認(rèn)為50)被壓縮到一個按鈕??梢栽凇霸O(shè)置”對話框的“常規(guī)”頁面的PyShell部分中更改N. 右鍵單擊輸出可以擠壓更少但可能超長的線條。通過雙擊按鈕或通過右鍵單擊按鈕進(jìn)入剪貼板或單獨(dú)的窗口,可以擴(kuò)展壓縮輸出。(由Tal Einat在bpo-1529353供稿。)
上述更改已被移植到3.7維護(hù)版本。
json.tool
添加選項–json-lines以將每個輸入行解析為單獨(dú)的JSON對象。(由Weipeng Hong在bpo-31553供稿。)
計算
增加math.dist()了計算兩點(diǎn)之間歐氏距離的新函數(shù)。
擴(kuò)展了math.hypot()處理多個維度的功能。以前,它只支持2-D案例。
添加了新函數(shù),math.prod()作為類似函數(shù)sum() 返回“start”值(默認(rèn)值:1)乘以可迭代數(shù)字的乘積。
os.path
os.path返回一個布爾值結(jié)果類似功能exists(),lexists(),isdir(), isfile(),islink(),和ismount()現(xiàn)在回到False代替升高ValueError或它的子類 UnicodeEncodeError,并UnicodeDecodeError為包含字符或字節(jié)在OS級不可表示的路徑。
expanduser()在Windows上現(xiàn)在更喜歡 USERPROFILE 環(huán)境變量,不使用 HOME,通常不為常規(guī)用戶帳戶設(shè)置。
ncurses
添加了一個新變量,其中包含底層ncurses庫的結(jié)構(gòu)化版本信息:ncurses_version。
pathlib
pathlib.Path返回布爾結(jié)果類似方法 exists(),is_dir(), is_file(),is_mount(), is_symlink(),is_block_device(), is_char_device(),is_fifo(), is_socket()現(xiàn)在回到False而不是提高 ValueError或它的子類UnicodeEncodeError的包含字符的不可表示在操作系統(tǒng)級別路徑。(由Serhiy Storchaka供稿于bpo-33721。)
shutil
shutil.copytree()現(xiàn)在接受一個新的dirs_exist_ok關(guān)鍵字參數(shù)。
SSL
添加SSLContext.post_handshake_auth以啟用和 ssl.SSLSocket.verify_client_post_handshake()啟動TLS 1.3握手后身份驗(yàn)證。
統(tǒng)計
添加statistics.fmean()為更快的浮點(diǎn)變體statistics.mean()。
添加statistics.multimode()了返回最常見值的列表。
添加statistics.NormalDist了一個用于創(chuàng)建和操作隨機(jī)變量的正態(tài)分布的工具.
1>>>
2>>> temperature_feb = NormalDist.from_samples([4, 12, -3, 2, 7, 14])
3>>> temperature_feb
4NormalDist(mu=6.0, sigma=6.356099432828281)
5
6>>> temperature_feb.cdf(3) # Chance of being under 3 degrees
70.3184678262814532
8>>> # Relative chance of being 7 degrees versus 10 degrees
9>>> temperature_feb.pdf(7) / temperature_feb.pdf(10)
101.2039930378537762
11
12>>> el_nino = NormalDist(4, 2.5)
13>>> temperature_feb += el_nino # Add in a climate effect
14>>> temperature_feb
15NormalDist(mu=10.0, sigma=6.830080526611674)
16
17>>> temperature_feb * (9/5) + 32 # Convert to Fahrenheit
18NormalDist(mu=50.0, sigma=12.294144947901014)
19>>> temperature_feb.samples(3) # Generate random samples
20[7.672102882379219, 12.000027119750287, 4.647488369766392]
tar文件
該tarfile模塊現(xiàn)在默認(rèn)為新檔案的現(xiàn)代pax(POSIX.1-2001)格式,而不是之前的GNU特定格式。這通過標(biāo)準(zhǔn)化和可擴(kuò)展格式的一致編碼(UTF-8)提高了跨平臺的可移植性,并提供了其他一些好處。
令牌化
當(dāng)提供沒有尾隨新行的輸入時,tokenize模塊現(xiàn)在隱式地發(fā)出NEWLINE令牌。此行為現(xiàn)在與C tokenizer在內(nèi)部執(zhí)行的操作相匹配。
Tkinter
添加的方法selection_from(), selection_present(), selection_range()和 selection_to() 在tkinter.Spinbox類。
moveto() 在tkinter.Canvas課堂上添加了方法。
時間
CLOCK_UPTIME_RAW為macOS 10.12 添加了新時鐘。
unicodedata
新函數(shù)is_normalized()可用于驗(yàn)證字符串是否處于特定的正常形式。
單元測試
添加addModuleCleanup()并 addClassCleanup()進(jìn)行unittest以支持setUpModule()和的 清理setUpClass()。
VENV
venv現(xiàn)在,Activate.ps1在PowerShell Core 6.1下,所有平臺上都包含一個用于激活虛擬環(huán)境的腳本。
XML
作為對DTD和外部實(shí)體檢索的緩解,默認(rèn)情況下, xml.dom.minidom和xml.sax模塊不再處理外部實(shí)體。
優(yōu)化
subprocess現(xiàn)在,模塊可以os.posix_spawn()在某些情況下使用該功能以獲得更好的性能。目前,如果滿足所有這些條件,它僅用于macOS和Linux
-close_fds為false;
未設(shè)置preexec_fn,pass_fds,cwd和start_new_session參數(shù);
該可執(zhí)行文件路徑中包含一個目錄。
-shutil.copyfile(),shutil.copy(),shutil.copy2(), shutil.copytree()并shutil.move()使用特定于平臺的“快速復(fù)制”在Linux,MacOS的和Solaris,以更有效地復(fù)制文件系統(tǒng)調(diào)用?!翱焖購?fù)制”意味著復(fù)制操作發(fā)生在內(nèi)核中,避免在Python中使用用戶空間緩沖區(qū),如“ outfd.write(infd.read())”。在Windows上shutil.copyfile()使用更大的默認(rèn)緩沖區(qū)大?。? MiB而不是16 KiB),并使用memoryview()基于a 的變體 - shutil.copyfileobj()。在同一分區(qū)中復(fù)制512 MiB文件的速度在Linux上約為+ 26%,在macOS上為+ 50%,在Windows上為+ 40%。此外,消耗的CPU周期更少。請參閱與平臺相關(guān)的高效復(fù)制操作部分。
shutil.copytree()使用os.scandir()函數(shù)和依賴它的所有復(fù)制函數(shù)使用緩存os.stat()值。復(fù)制具有8000個文件的目錄的速度在Linux上約為+ 9%,在Windows上為+ 20%,在Windows SMB共享上為+ 30%。此外,os.stat() 系統(tǒng)調(diào)用的數(shù)量減少了38%,使shutil.copytree()網(wǎng)絡(luò)文件系統(tǒng)的速度更快。
-pickle模塊中的默認(rèn)協(xié)議現(xiàn)在是協(xié)議4,首先在Python 3.4中引入。與Python 3.0以來提供的Protocol 3相比,它提供了更好的性能和更小的尺寸。
刪除了一個Py_ssize_t成員PyGC_Head。所有GC跟蹤對象(例如元組,列表,字典)的大小減少了4或8個字節(jié)。
uuid.UUID現(xiàn)在用于slots__減少其內(nèi)存占用。 -性能提升operator.itemgetter()了33%。優(yōu)化參數(shù)處理并為單個非負(fù)整數(shù)索引的常見情況添加快速路徑到元組(這是標(biāo)準(zhǔn)庫中的典型用例)。 -加速字段查找collections.namedtuple()。它們現(xiàn)在的速度提高了兩倍以上,使它們成為Python中最快的實(shí)例變量查找形式。 -list如果輸入iterable具有已知長度(輸入實(shí)現(xiàn)__len),則構(gòu)造函數(shù)不會全局定位內(nèi)部項緩沖區(qū)。這使得創(chuàng)建的列表平均減少12%。(由Raymond Hettinger和Pablo Galindo在bpo-33234中提供。)
-將類變量寫入的速度加倍。更新非dunder屬性時,會有不必要的更新插槽調(diào)用。(由Stefan Behnel,Pablo Galindo Salgado,Raymond Hettinger,Neil Schemenauer和Serhiy Storchaka供稿于bpo-36012。)
-減少轉(zhuǎn)換傳遞給許多內(nèi)置函數(shù)和方法的參數(shù)的開銷。加快調(diào)用一些簡單的內(nèi)置函數(shù)和方法,最多可達(dá)20-50%。(由Serhiy Storchaka在bpo-23867, bpo-35582和bpo-36127供稿。)
構(gòu)建和C API更改
這些PyByteArray_Init()和PyByteArray_Fini()功能已被刪除。他們沒有做任何事情,因?yàn)镻ython 2.7.4和Python 3.2.0被排除在有限的API(穩(wěn)定的ABI)之外,并且沒有記錄。
結(jié)果PyExceptionClass_Name()現(xiàn)在是類型 而不是。const char *char *
二元性Modules/Setup.dist和 Modules/Setup已被刪除。以前,在更新CPython源代碼樹時,必須手動將Modules/Setup.dist(在源代碼樹內(nèi))復(fù)制到 Modules/Setup(在構(gòu)建樹內(nèi))以反映上游的任何更改。這對包裝商來說是一個小小的好處,代價是CPython開發(fā)后開發(fā)人員經(jīng)常煩惱,因?yàn)橥洀?fù)制文件可能會導(dǎo)致構(gòu)建失敗。
現(xiàn)在構(gòu)建系統(tǒng)總是從Modules/Setup源樹內(nèi)部讀取。鼓勵想要自定義該文件的人將其更改保存在CPython的git fork中或作為補(bǔ)丁文件,就像它們對源樹的任何其他更改一樣。
將Python數(shù)轉(zhuǎn)換為C整數(shù)的 PyLong_AsLong()函數(shù)和參數(shù)解析函數(shù)(如 PyArg_ParseTuple()整數(shù)轉(zhuǎn)換格式單位)‘i’ 現(xiàn)在將使用__index__()特殊方法而不是( int__()如果可用)。將使用_int_()方法但沒有 index()方法(如Decimal和 Fraction)為對象發(fā)出棄用警告。 PyNumber_Check()現(xiàn)在將返回 1實(shí)現(xiàn)的對象__index()。
堆分配的類型對象現(xiàn)在將增加它們PyObject_Init()(和它的并行宏P(guān)yObject_INIT)中的引用計數(shù)而不是in PyType_GenericAlloc()。可能需要調(diào)整修改實(shí)例分配或釋放的類型。
不支持
不建議使用的方法getchildren(),getiterator()在ElementTree模塊現(xiàn)在發(fā)出 DeprecationWarning來代替PendingDeprecationWarning。它們將在Python 3.9中刪除。
傳遞一個不是concurrent.futures.ThreadPoolExecutorto的實(shí)例的對象已 asyncio.loop.set_default_executor()被棄用,并且將在Python 3.9中被禁止。
該getitem()方法xml.dom.pulldom.DOMEventStream, wsgiref.util.FileWrapper并fileinput.FileInput已被棄用。
這些方法的實(shí)現(xiàn)忽略了它們的索引參數(shù),而是返回下一個項目。
該typing.NamedTuple已否決了,_field_types贊成的屬性__annotations__具有相同信息的屬性。
ast類Num,Str,Bytes,NameConstant和 Ellipsis被標(biāo)記是過時的,并將在未來的Python版本中刪除。Constant應(yīng)該用來代替。
下面的函數(shù)和方法棄用在gettext 模塊:lgettext(),ldgettext(), lngettext()和ldngettext()。它們返回編碼的字節(jié),如果翻譯的字符串存在編碼問題,則可能會出現(xiàn)意外的與Unicode相關(guān)的異常。在Python 3中使用返回Unicode字符串的替代方法要好得多。這些功能已經(jīng)被打破了很長時間。
功能bind_textdomain_codeset(),方法 output_charset()和 set_output_charset(),以及代碼集 的功能參數(shù)translation()和install()也不贊成使用,因?yàn)樗鼈儍H用于為l*gettext()功能。
-該isAlive()方法threading.Thread已被棄用。
許多帶有整數(shù)參數(shù)的內(nèi)置函數(shù)和擴(kuò)展函數(shù)現(xiàn)在將為Decimals,F(xiàn)ractions和任何其他對象發(fā)出棄用警告, 這些對象只能在丟失的情況下轉(zhuǎn)換為整數(shù)(例如,具有int__() 方法但沒有__index()方法)。在將來的版本中,它們將是錯誤的。
API和功能刪除
從Python 3.8
中刪除了以下功能和API:
macpath已刪除在Python 3.7中棄用的模塊。
該函數(shù)platform.popen()已被刪除,自Python 3.3以來已被棄用:os.popen()改為使用。
該pyvenv腳本已被刪除, 以幫助消除關(guān)于 腳本綁定的Python解釋器的混淆。python3.8 -m venvpyvenv
parse_qs,parse_qsl和escape從除去cgi 模塊。它們已從Python 3.2或更早版本棄用。
filemode功能已從tarfile模塊中刪除。自Python 3.3以來,它沒有記錄和棄用。
該XMLParser構(gòu)造不再接受HTML參數(shù)。它從未產(chǎn)生過影響,在Python 3.4中已被棄用。所有其他參數(shù)現(xiàn)在都是僅關(guān)鍵字。
刪除了doctype()方法XMLParser。
unicode_internal編解碼器被刪除。
移植
本節(jié)列出了先前描述的更改以及可能需要更改代碼的其他錯誤修正。
屈服表達(dá)式(both yield和子句)現(xiàn)在在理解和生成器表達(dá)式中是不允許的(除了最左邊的子句中的可迭代表達(dá)式)
編譯器現(xiàn)在生成一個SyntaxWarning何時身份檢查 與某些類型的文字(例如字符串,整數(shù))一起使用。這些通??梢栽贑Python中偶然使用,但不受語言規(guī)范的保證。警告建議用戶使用相等測試。
Python API的變化
該函數(shù)platform.popen()已被刪除,自Python 3.3以來已被棄用:os.popen()改為使用。
statistics.mode()給定多模態(tài)數(shù)據(jù)時,該函數(shù)不再引發(fā)異常。相反,它返回輸入數(shù)據(jù)中遇到的第一個模式。
該類的selection()方法 tkinter.ttk.Treeview不再需要參數(shù)。在Python 3.6中不推薦使用帶有參數(shù)來更改選擇。使用專門的方法,如selection_set()更改選擇。
writexml(),toxml()并且toprettyxml()所述的方法 xml.dom.minidom模塊,和xml.etree現(xiàn)在保存由用戶指定的屬性順序。(
-dbm.dumb使用flags打開的數(shù)據(jù)庫’r’現(xiàn)在是只讀的。 dbm.dumb.open()帶有標(biāo)志’r’,'w’如果不存在則不再創(chuàng)建數(shù)據(jù)庫。
將不再調(diào)用doctype()子類中定義的方法, XMLParser并且將導(dǎo)致發(fā)出a RuntimeWarning而不是a DeprecationWarning。doctype()在目標(biāo)上定義用于處理XML doctype聲明的方法。
一個RuntimeError是現(xiàn)在時引發(fā)自定義的元類不提供classcell__傳入的名稱空間項 type.__new。A DeprecationWarning是在Python 3.6-3.7中發(fā)出的。
在cProfile.Profile類現(xiàn)在可以作為一個上下文管理器。
shutil.copyfile(),shutil.copy(),shutil.copy2(), shutil.copytree()并shutil.move()使用特定于平臺的“快速復(fù)制”的系統(tǒng)調(diào)用
shutil.copyfile()Windows上的默認(rèn)緩沖區(qū)大小從16 KiB更改為1 MiB。
PyGC_Head結(jié)構(gòu)完全改變了。觸及struct成員的所有代碼都應(yīng)該被重寫。
PyInterpreterState結(jié)構(gòu)已被移入“內(nèi)部”頭文件(特別是Include / internal / pycore_pystate.h)。opaque PyInterpreterState仍然可用作公共API(和穩(wěn)定的ABI)的一部分。文檔表明struct的字段都不公開,所以我們希望沒有人使用它們。但是,如果您確實(shí)依賴于一個或多個私有字段而沒有其他選擇,那么請打開一個BPO問題。我們將努力幫助您進(jìn)行調(diào)整(可能包括向公共API添加訪問器功能)。
ASYNCIO任務(wù)現(xiàn)在可以命名,或者通過將name關(guān)鍵字參數(shù)asyncio.create_task()或create_task()事件循環(huán)的方法,或者通過調(diào)用set_name()任務(wù)對象的方法。任務(wù)名稱在repr()輸出中可見,asyncio.Task也可以使用該get_name()方法檢索。
mmap.flush()方法現(xiàn)在返回None成功并在所有平臺下引發(fā)錯誤異常。以前,它的行為是平臺依賴的:成功時返回非零值; 在Windows下錯誤返回零。成功返回零值; 在Unix下出現(xiàn)異常錯誤。
該函數(shù)math.factorial()不再接受非int類的參數(shù)。
xml.dom.minidom和xml.sax模塊默認(rèn)不再處理外部實(shí)體。
從只讀dbm數(shù)據(jù)庫(dbm.dumb, dbm.gnu或dbm.ndbm)中刪除密鑰會引發(fā)error(dbm.dumb.error, dbm.gnu.error或dbm.ndbm.error)而不是KeyError。
expanduser()在Windows上現(xiàn)在更喜歡 USERPROFILE 環(huán)境變量,不使用 HOME,通常不為常規(guī)用戶帳戶設(shè)置。
使用#在分析或建筑價值的形式變體(例如 PyArg_ParseTuple(),Py_BuildValue(),PyObject_CallFunction()沒有等)PY_SSIZE_T_CLEAN定義提出了DeprecationWarning現(xiàn)在。它將在3.10或4.0中刪除。閱讀解析參數(shù)并為細(xì)節(jié)構(gòu)建值。(由Inada Naoki在bpo-36381供稿。)
C API的變化
-堆分配類型的實(shí)例(例如用其創(chuàng)建的實(shí)例 PyType_FromSpec())保存對其類型對象的引用。增加這些類型對象的引用計數(shù)已從 PyType_GenericAlloc()更低級別的函數(shù)移動, PyObject_Init()并且PyObject_INIT()。這使得通過PyType_FromSpec()托管代碼中的其他類行為創(chuàng)建類型。
靜態(tài)分配的類型不受影響。
對于絕大多數(shù)情況,應(yīng)該沒有副作用。但是,在分配實(shí)例(可能是為了解決bug)之后手動增加引用計數(shù)的類型現(xiàn)在可能變得不朽。為避免這種情況,這些類需要在實(shí)例釋放期間在類型對象上調(diào)用Py_DECREF。
要將這些類型正確移植到3.8,請應(yīng)用以下更改:
Py_INCREF分配實(shí)例后刪除類型對象 - 如果有的話。這可能打完電話后發(fā)生的PyObject_New(), PyObject_NewVar(),PyObject_GC_New(), PyObject_GC_NewVar(),或使用任何其他自定義分配器 PyObject_Init()或PyObject_INIT()。
例:
1static foo_struct *
2foo_new(PyObject *type) {
3 foo_struct *foo = PyObject_GC_New(foo_struct, (PyTypeObject *) type);
4 if (foo == NULL)
5 return NULL;
6#if PY_VERSION_HEX < 0x03080000
7 // Workaround for Python issue 35810; no longer necessary in Python 3.8
8 PY_INCREF(type)
9#endif
10 return foo;
11}
確保 tp_dealloc堆分配類型的所有自定義函數(shù)都減少了類型的引用計數(shù)。
例:
1 static void
2foo_dealloc(foo_struct *instance) {
3 PyObject *type = Py_TYPE(instance);
4 PyObject_GC_Del(instance);
5#if PY_VERSION_HEX >= 0x03080000
6 // This was not needed before Python 3.8 (Python issue 35810)
7 Py_DECREF(type);
8#endif
9}
CPython字節(jié)碼更改
通過移動將塊堆棧展開到編譯器中的邏輯,簡化了解釋器循環(huán)。編譯器現(xiàn)在發(fā)出顯式指令,用于調(diào)整值堆棧并調(diào)用清理代碼break,continue和 return。
刪除操作碼BREAK_LOOP,CONTINUE_LOOP, SETUP_LOOP和SETUP_EXCEPT。增加了新的操作碼ROT_FOUR,BEGIN_FINALLY,CALL_FINALLY和 POP_FINALLY。改變了END_FINALLY和WITH_CLEANUP_START。 添加了新的操作碼,END_ASYNC_FOR`用于處理在等待循環(huán)中的下一個項目時引發(fā)的異常。