[譯文]python2還是python3

原文: https://wiki.python.org/moin/Python2orPython3

在項(xiàng)目開發(fā)中,我應(yīng)該用python2還是python3?

它們之間有什么區(qū)別?

簡而言之,python2.x是過去;python3.x是現(xiàn)在、是將來。

在2008年的時(shí)候,python3.0發(fā)布。python2.x的最后版--v2.7也于2010年年中發(fā)布,并且聲明了對(duì)最后一版的延長支持。在這之后,python2.x分支就沒有任何主要的新屬性發(fā)布。3.x版本一直持續(xù)開發(fā),并且已經(jīng)發(fā)布了5年的穩(wěn)定版本。2012年發(fā)布3.3,2014年發(fā)布3.4,2015年發(fā)布3.5,2016年發(fā)布3.6。這意味著新開發(fā)的標(biāo)準(zhǔn)庫只在python3.x中展現(xiàn)。

在最新的2.x發(fā)布版本中,Guido van Rossum(python的創(chuàng)造者)決定適當(dāng)?shù)那謇韕ython2.x,以減少向后兼容性。最大的改變是更好的unicode編碼支持(默認(rèn)情況下所有文字都轉(zhuǎn)換成unicode)與更加健全的bytes/unicode編碼分離。

此外,在幾個(gè)核心語言層面,做了一些調(diào)整(如,print與exec是聲明,整數(shù)使用向下取整)。這些改變對(duì)初學(xué)者來說,更加容易學(xué)習(xí)。對(duì)Python其他部分也更加易用。一些老舊的丑陋的代碼被移除,舉個(gè)例子,所有的類都是new-style,"range"函數(shù)不再像python2.x一樣返回list, 而是返回一個(gè)內(nèi)存利用率高的迭代器。

《python3.0中的新特性》對(duì)于主要的語言層改變以及與python2.x源碼可能存在的兼用性做了一個(gè)很好的概述。Nick Coghlan(CPython開發(fā)者之一)也創(chuàng)建了一個(gè)relatively extensive FAQ來處理python版本過渡問題。

然而,在過去的時(shí)間里,龐大的python生態(tài)系統(tǒng)已經(jīng)累積了大量的重要的高質(zhì)量的軟件。對(duì)python3.x的兼容的最大問題就是,某些軟件(尤其是一些公司內(nèi)部軟件)任然不能再python3.x下正常運(yùn)行。

該如何選擇我要使用的版本?

如何選擇版本,主要依賴于你想要做什么。

如果你明確的知道用python3想要做什么。很好,這里有少許次要的缺陷或不足,如不是太嚴(yán)重的軟件庫支持問題,還有一個(gè)客觀事實(shí)是,現(xiàn)在的很多l(xiāng)inux發(fā)行版和mac都是將python2作為默認(rèn)python版本(雖然在很多系統(tǒng)中,python3也被安裝了),python3有著一個(gè)語言應(yīng)該有的所有特性。如果你能控制你所安裝的環(huán)境并且你明確知道你不需要python2的模塊,使用python3是一個(gè)很好的選擇。現(xiàn)在,很多的linux發(fā)行版已經(jīng)內(nèi)置了python3。并且所有這些都適用于終端用戶。一些linux已經(jīng)開始淘汰python2作為內(nèi)置python版本。

特別指出的是,很多教師或書籍在介紹python的時(shí)候都會(huì)首先考慮python3,而后,如果有必要,再介紹python3與python2的不同之處。因?yàn)閜ython3移除了一些,初學(xué)者學(xué)習(xí)python2而踩的一些不必要的坑。

然而,任然有一些問題需要你必須用python2而不是用python3。

  • 你的應(yīng)用所部署的環(huán)境是一個(gè)你不能控制的。這個(gè)環(huán)境中使用了特殊版本的python,而不是讓你自由選擇python版本。
  • 你依賴的三方庫沒有兼容python3。并且這個(gè)庫是一個(gè)不可或缺或及其重要的庫。

python3在使用創(chuàng)建GUI應(yīng)用已經(jīng)得到了廣泛的支持。包Tkinter作為標(biāo)準(zhǔn)庫。從python3發(fā)布開始,PyQt也被支持。 在2011年,PySide被支持。PyGObject作為PyGtk的替代品也被支持。

這里列舉了一些主要的支持python3的包:

如果你想使用python3,但是你又害怕依賴兼容性問題。使用之前,做一些調(diào)研是值得的。這是一個(gè)持續(xù)跟進(jìn)的過程,這篇wiki也可能過時(shí)。此外,有著對(duì)于python2.6+與python3.3+的大量支持,現(xiàn)在很多的python代碼都不需要做較大的修改就可以運(yùn)行在python3上。尤其是用于web與GUI框架的代碼,這些框架強(qiáng)制應(yīng)用區(qū)別二進(jìn)制數(shù)據(jù)與文本(six compatiblility module可以用來修補(bǔ)這些問題)。

雖然官方文檔tutorial對(duì)python3鏡像完整的更新。但是在網(wǎng)上與一些相關(guān)的書籍中的大量的文檔是使用python2。這些文檔雖然也在不斷的更新。當(dāng)用python3來運(yùn)行的時(shí)候需要做一些調(diào)整。

有些人不想用python3。這是他們的權(quán)利。畢竟是少數(shù)人。

如果你想用其他一些python執(zhí)行環(huán)境,如IronPython,Jython 或Pyston等等,使用python3是不值得的。在這些平臺(tái)中python3的支持還是不太理想。當(dāng)你應(yīng)為系統(tǒng)的完整性或性能等等原因而選擇前面所說的執(zhí)行環(huán)境的時(shí)候,這個(gè)因素(在這些平臺(tái)上,python3支持有限)將會(huì)影響你。

難道我不想避免使用python2? python2是一門有許多錯(cuò)誤的老語言了,python已經(jīng)開了一個(gè)主版本來移除這些錯(cuò)誤。

good, 也不完全是,一些python3.0,python3.1的斷層式的修改已經(jīng)各自被移植到python2.6, 2.7。更多的移植相關(guān),參見What's New in Python2.6What's New in Python2.7

對(duì)于哪些屬性只能用在python3與哪些屬性不能移植到python2沒有一個(gè)詳盡的列表列出。

  • 字符串默認(rèn)編碼為Unicode
  • 清除unicode與bytes分離
  • 異常鏈
  • 函數(shù)注解
  • 關(guān)鍵詞參數(shù)語法
  • 擴(kuò)展的tuple解包
  • 沒有局部變量定義

語言版本的更迭,并沒有限制核心代碼的改變。在標(biāo)準(zhǔn)庫中,一些在python3中的改善并沒有直接移植到python2。參見What's New in Python3。一些標(biāo)準(zhǔn)庫的提升可以通過PyPI找到。

也就是說,用python2寫的代碼更加像python3的代碼。這可以代表很多事情。包括使用新類型的classe,不使用古老的棄用的print用法,使用懶加載的迭代器。舉個(gè)例子,好的python2代碼會(huì)用xrange來代替range。xrange最開始在python3上的range實(shí)現(xiàn)(當(dāng)然,range在python3中表現(xiàn)更好一些,因?yàn)樗梢詇andle住超過sys.maxint的值)。有點(diǎn)值得注意的是xrange()在python3中沒有被定義。

最終要的是,python2或python3只是些小問題,你真正應(yīng)該做的是寫好好代碼。這些代碼包含完整的單元測(cè)試,正確的使用unicode。(在unicode與bytes問題上,python3相對(duì)于python2更少的操心。這是一件好事情,雖然這讓一些軟件包的移植變得相對(duì)來說比較惡心)

我想用Python3,但是想用的一些庫只有python2。難道我只能不得不重新回去使用python2或者放棄使用這個(gè)庫?

假設(shè)你找不到在python3中支持替代包,你可以看看下面的幾種建議:

  • 移植這個(gè)庫到python3 ("porting"意味著你需要讓這個(gè)庫能正常的在python3上運(yùn)行)
  • 如果實(shí)在是實(shí)現(xiàn)比較困難,并且你的其他依賴也是用python2,你可以開始的時(shí)候用python2。隨著庫在其他地方被移植的,一旦每一個(gè)依賴庫度偶做好了移植,好的python2代碼可以進(jìn)行輕松的切換。
  • 好好想想這個(gè)庫是否真的很重要?或許你可以不使用它。

最理想的狀態(tài)是你試著移植到python3,你經(jīng)常發(fā)現(xiàn)有人使用它,即使不是當(dāng)前庫,其他成員通常會(huì)感激你的。尤其是移植中發(fā)現(xiàn)原始的bug。這樣做可以提高原始版本與python3移植版本的質(zhì)量。移植不是一帆風(fēng)順的,但總是比你自己從頭開始寫容易。

Python2 porting guide中,你可以知道如何移植庫。最基本的思想是使用python2庫,在python2中使用-3 命令切換,檢查所有的單元測(cè)試通過,而沒有警告。如果測(cè)試失敗,或者發(fā)出了警告信息。修改源碼,再一次做單元測(cè)試(這可能需要在老的版本中降低兼容性)。當(dāng)沒有警告信息的時(shí)候,可以試著用python3運(yùn)行這個(gè)庫了。最好的可能的狀態(tài)是運(yùn)行的代碼是python2,python3兼容的,這時(shí)候,移植完成。

如果在python3中,單元測(cè)試任然失敗。那么標(biāo)準(zhǔn)庫中的2to3組件能夠自動(dòng)生成運(yùn)行在python3下的版本。或者Armin Ronacher的python-modernize組件可以用于python2.6+和3.2+或者3.3+(這依賴于命令行輸出參數(shù))。如果你使用python-modernize,同樣需要在Python2下做單元測(cè)試。

任一種方法都可以從單個(gè)python2代碼庫并行支持python2和python3。將python2與python3分開維護(hù)更加容易一些。(可以問問核心代碼開發(fā)者,他們這么做已經(jīng)很多年了)

如果自動(dòng)轉(zhuǎn)換后,測(cè)試失敗,有可能是因?yàn)閜ython3與python2的語義變化。這些變化有可能導(dǎo)致轉(zhuǎn)換器自動(dòng)轉(zhuǎn)換失敗,-3 switch也沒有檢測(cè)出來。這些問題不多,但是也是存在的。當(dāng)你遇到的時(shí)候,提交一個(gè)bug給CPython,請(qǐng)求一個(gè)新的 -3 警告,是非常值得的。

如果包含c擴(kuò)展或者工程沒有使用想CPython,cffi,SWIG這些能夠值得處理python2與python3之間的差異的包裹生成器,移植過程可能更加復(fù)雜。但是還是會(huì)比你自己開發(fā)相同功能的包更容易一些。extension porting guide介紹了一些它們之間的主要的不同之處。

這里是一些比較深入的guide:PortingPythonToPy3k,PortingExtensionModulesToPy3k

我想用python3寫一些東西,但是有些人只用python2,我該怎么辦?

除了有能夠從python2代碼生成python3代碼的2to3工具,還有轉(zhuǎn)換python3代碼到python2代碼的3to2工具。理論上,可以3to2可能比2to3工作得更好,因?yàn)閜ython3對(duì)轉(zhuǎn)換器轉(zhuǎn)換來數(shù),清理掉了許多惡心的死角問題(畢竟,盡可能擺脫更多的這種問題是打破向后兼容性的主要原因之一)。然而,那些嚴(yán)重依賴python3特有屬性的代碼(例如函數(shù)注解,擴(kuò)展版tuple unpacking)是不可能轉(zhuǎn)換成功的。

可以舉個(gè)恰當(dāng)?shù)谋确剑?to2相對(duì)于2to3來說是一條更少旅人的路你可能遇到一些邊邊角角。如果你想用python3, 這些是值得探索的。

在一些通用模塊代碼中支持python2與python3

python2.6+與python3.3+有大量的相同之處。例如,在python3中對(duì)unicode字符串前面加'u'字符的恢復(fù)意味著語義上正確的python2.6+代碼可以與python3.3+兼容,同時(shí)保留著大量的慣用的python。主要的不同是來自不同地方的代碼需要被修改,這樣才可以處理python2與python3之間的命名問題。

因此,six compatibility package是在單一庫中支持python2與python3最主要的實(shí)用程序。

future compatibility package任然在測(cè)試中,并且不像six包一樣支持如此多的python版本(future只支持到python2.6, six可以支持到python2.4)。但是future運(yùn)行python2兼容代碼可以寫得跟python3通用代碼一樣的風(fēng)格(例如,它包含了python2兼容python3中bytes類型實(shí)現(xiàn)代碼,而不是依賴于python2中的字節(jié)字符串類型,他們兩個(gè)是不同的API)。

其他一些確定標(biāo)準(zhǔn)庫的主要的因素是是否存在一個(gè)更新的對(duì)PyPi的移植,這些移植優(yōu)先用于python2標(biāo)準(zhǔn)庫。下面所列的這些模塊要么是對(duì)PyPI的移植,要么是原生支持python2.7與python3標(biāo)準(zhǔn)庫:

  • unittest2(Michael Foord, 標(biāo)準(zhǔn)庫unittest維護(hù)者, 需要2.6支持)
  • mock(Michael Foord, 標(biāo)準(zhǔn)庫unittest.mock維護(hù)者)
  • contextlib2(Nick Coghlan, 標(biāo)準(zhǔn)庫contextlib維護(hù)者)
  • configparser(?ukasz Langa, 標(biāo)準(zhǔn)庫configparser維護(hù)者)
  • futures(Alex Gr?nholm and Brian Quinlan, 標(biāo)準(zhǔn)庫concurrent.futures維護(hù)者)
  • argparse(Steven Bethard, 標(biāo)準(zhǔn)庫argparse維護(hù)者, 需要2.6支持)
  • faulthandler(Victor Stinner,標(biāo)準(zhǔn)庫faulthandler維護(hù)者)
  • cdecimal(Stefan Krah, 標(biāo)準(zhǔn)庫decimal維護(hù)者)
  • ipaddr((Peter Moody, 標(biāo)準(zhǔn)庫ipaddress維護(hù)者)
  • stats(Steven D'Aprano, 標(biāo)準(zhǔn)庫statistics維護(hù)者)
  • enum34(Ethan Furman,標(biāo)準(zhǔn)庫enum維護(hù)者)
  • funcsigs(Aaron Iles,移植于函數(shù)signature objects)
  • shared namespace module for backports(Brandon Craig Rhodes)
  • backports.inspect(Tripp Lilley, 額外的inspect移植,基于funcsigs)
  • backports.datetime_timestamp(Jason R. Coombs, datetime.timestamp的移植)
  • backports.pbkdf2(Christian Heimes, 標(biāo)準(zhǔn)庫hashlib維護(hù)者, 對(duì)hashlib.pbkdf2_hmac的移植)
  • backports.ssl_match_hostname(Brandom Craig Rhodes 與 Toshio Kuratomi, ssl.match_hostname的移植)
  • backports.lzma(Peter Cock, lzma wrapper模塊的移植)
  • lzmaffi(Tomer Chachamu, lzma的移植)
  • tracemalloc(Victor Stinner, 標(biāo)準(zhǔn)庫tracemalloc的維護(hù)者)
  • pathlib(Antoine Pitrou, 標(biāo)準(zhǔn)庫pathlib的維護(hù)者)
  • selectors34(Berker Peksag,標(biāo)準(zhǔn)庫selectors的移植)

當(dāng)在交叉版本的標(biāo)準(zhǔn)庫之間使用,使用移植版本的命名空間模塊可以清楚的指明。原始版本的屬性可以使用而不會(huì)產(chǎn)生沖突。

下面的模塊不是移植版本。但是可以替換標(biāo)準(zhǔn)版本的各個(gè)版本兼容的庫。

  • requests(對(duì)http/https更高級(jí)封裝的api)
  • regex(一個(gè)替代的正則表達(dá)式引擎)
  • lxml.etree(ElementTree XML API的替代實(shí)現(xiàn))

上面的這些模塊也支持python2。在python3.4中,asyncio模塊被添加到標(biāo)準(zhǔn)庫中。

  • asyncio(Guido van Rossum, BDFL and標(biāo)準(zhǔn)庫 asyncio維護(hù)者)

其他一些有助于在python2,python3做選擇的資源

補(bǔ)充說明

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

推薦閱讀更多精彩內(nèi)容