原文: https://wiki.python.org/moin/Python2orPython3
在項(xiàng)目開發(fā)中馆纳,我應(yīng)該用python2還是python3?
它們之間有什么區(qū)別逮京?
簡而言之,python2.x是過去;python3.x是現(xiàn)在峡继、是將來岸梨。
在2008年的時候,python3.0發(fā)布篷扩。python2.x的最后版--v2.7也于2010年年中發(fā)布兄猩,并且聲明了對最后一版的延長支持。在這之后鉴未,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編碼分離坯汤。
此外虐唠,在幾個核心語言層面,做了一些調(diào)整(如惰聂,print與exec是聲明疆偿,整數(shù)使用向下取整)。這些改變對初學(xué)者來說搓幌,更加容易學(xué)習(xí)杆故。對Python其他部分也更加易用。一些老舊的丑陋的代碼被移除溉愁,舉個例子处铛,所有的類都是new-style,"range"函數(shù)不再像python2.x一樣返回list, 而是返回一個內(nèi)存利用率高的迭代器。
《python3.0中的新特性》對于主要的語言層改變以及與python2.x源碼可能存在的兼用性做了一個很好的概述拐揭。Nick Coghlan(CPython開發(fā)者之一)也創(chuàng)建了一個relatively extensive FAQ來處理python版本過渡問題撤蟆。
然而,在過去的時間里堂污,龐大的python生態(tài)系統(tǒng)已經(jīng)累積了大量的重要的高質(zhì)量的軟件家肯。對python3.x的兼容的最大問題就是,某些軟件(尤其是一些公司內(nèi)部軟件)任然不能再python3.x下正常運(yùn)行盟猖。
該如何選擇我要使用的版本讨衣?
如何選擇版本换棚,主要依賴于你想要做什么。
如果你明確的知道用python3想要做什么。很好,這里有少許次要的缺陷或不足链方,如不是太嚴(yán)重的軟件庫支持問題福荸,還有一個客觀事實(shí)是,現(xiàn)在的很多l(xiāng)inux發(fā)行版和mac都是將python2作為默認(rèn)python版本(雖然在很多系統(tǒng)中,python3也被安裝了),python3有著一個語言應(yīng)該有的所有特性。如果你能控制你所安裝的環(huán)境并且你明確知道你不需要python2的模塊风秤,使用python3是一個很好的選擇。現(xiàn)在扮叨,很多的linux發(fā)行版已經(jīng)內(nèi)置了python3缤弦。并且所有這些都適用于終端用戶。一些linux已經(jīng)開始淘汰python2作為內(nèi)置python版本彻磁。
特別指出的是碍沐,很多教師或書籍在介紹python的時候都會首先考慮python3,而后衷蜓,如果有必要累提,再介紹python3與python2的不同之處。因?yàn)閜ython3移除了一些磁浇,初學(xué)者學(xué)習(xí)python2而踩的一些不必要的坑斋陪。
然而,任然有一些問題需要你必須用python2而不是用python3置吓。
- 你的應(yīng)用所部署的環(huán)境是一個你不能控制的无虚。這個環(huán)境中使用了特殊版本的python,而不是讓你自由選擇python版本衍锚。
- 你依賴的三方庫沒有兼容python3友题。并且這個庫是一個不可或缺或及其重要的庫。
python3在使用創(chuàng)建GUI應(yīng)用已經(jīng)得到了廣泛的支持戴质。包Tkinter作為標(biāo)準(zhǔn)庫度宦。從python3發(fā)布開始,PyQt也被支持置森。 在2011年斗埂,PySide被支持符糊。PyGObject作為PyGtk的替代品也被支持凫海。
這里列舉了一些主要的支持python3的包:
- NumPy 與 SciPy(科學(xué)計(jì)算)
- Django、Flask男娄、CherryPy行贪、Pyramid(web開發(fā))
- Pyramid(圖片處理漾稀,代替PIL)
- cx_Freeze(將python文件打包成可執(zhí)行文件)
- py2exe(打包成window可執(zhí)行文件)
- OpenCV 3(開源的機(jī)器學(xué)習(xí)與計(jì)算機(jī)圖形庫)
- requests(http請求庫)
- lxml(python xml解析庫)
- BeautifulSoup4(html dom解析庫)
- ipython與jupyter(交互計(jì)算)
- 等等
如果你想使用python3,但是你又害怕依賴兼容性問題。使用之前建瘫,做一些調(diào)研是值得的崭捍。這是一個持續(xù)跟進(jìn)的過程,這篇wiki也可能過時啰脚。此外殷蛇,有著對于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對python3鏡像完整的更新荸实。但是在網(wǎng)上與一些相關(guān)的書籍中的大量的文檔是使用python2匀们。這些文檔雖然也在不斷的更新。當(dāng)用python3來運(yùn)行的時候需要做一些調(diào)整准给。
有些人不想用python3泄朴。這是他們的權(quán)利。畢竟是少數(shù)人露氮。
如果你想用其他一些python執(zhí)行環(huán)境祖灰,如IronPython,Jython 或Pyston等等,使用python3是不值得的畔规。在這些平臺中python3的支持還是不太理想夫植。當(dāng)你應(yīng)為系統(tǒng)的完整性或性能等等原因而選擇前面所說的執(zhí)行環(huán)境的時候,這個因素(在這些平臺上油讯,python3支持有限)將會影響你详民。
難道我不想避免使用python2? python2是一門有許多錯誤的老語言了,python已經(jīng)開了一個主版本來移除這些錯誤陌兑。
good, 也不完全是沈跨,一些python3.0,python3.1的斷層式的修改已經(jīng)各自被移植到python2.6, 2.7。更多的移植相關(guān)兔综,參見What's New in Python2.6與What's New in Python2.7
對于哪些屬性只能用在python3與哪些屬性不能移植到python2沒有一個詳盡的列表列出饿凛。
- 字符串默認(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用法,使用懶加載的迭代器糖儡。舉個例子伐坏,好的python2代碼會用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)該做的是寫好好代碼呐矾。這些代碼包含完整的單元測試苔埋,正確的使用unicode。(在unicode與bytes問題上蜒犯,python3相對于python2更少的操心组橄。這是一件好事情,雖然這讓一些軟件包的移植變得相對來說比較惡心)
我想用Python3,但是想用的一些庫只有python2罚随。難道我只能不得不重新回去使用python2或者放棄使用這個庫玉工?
假設(shè)你找不到在python3中支持替代包,你可以看看下面的幾種建議:
- 移植這個庫到python3 ("porting"意味著你需要讓這個庫能正常的在python3上運(yùn)行)
- 如果實(shí)在是實(shí)現(xiàn)比較困難淘菩,并且你的其他依賴也是用python2,你可以開始的時候用python2遵班。隨著庫在其他地方被移植的,一旦每一個依賴庫度偶做好了移植潮改,好的python2代碼可以進(jìn)行輕松的切換狭郑。
- 好好想想這個庫是否真的很重要?或許你可以不使用它汇在。
最理想的狀態(tài)是你試著移植到python3,你經(jīng)常發(fā)現(xiàn)有人使用它翰萨,即使不是當(dāng)前庫,其他成員通常會感激你的糕殉。尤其是移植中發(fā)現(xiàn)原始的bug亩鬼。這樣做可以提高原始版本與python3移植版本的質(zhì)量。移植不是一帆風(fēng)順的,但總是比你自己從頭開始寫容易阿蝶。
在Python2 porting guide中雳锋,你可以知道如何移植庫。最基本的思想是使用python2庫羡洁,在python2中使用-3 命令切換玷过,檢查所有的單元測試通過,而沒有警告。如果測試失敗冶匹,或者發(fā)出了警告信息习劫。修改源碼咆瘟,再一次做單元測試(這可能需要在老的版本中降低兼容性)嚼隘。當(dāng)沒有警告信息的時候,可以試著用python3運(yùn)行這個庫了袒餐。最好的可能的狀態(tài)是運(yùn)行的代碼是python2,python3兼容的飞蛹,這時候,移植完成灸眼。
如果在python3中卧檐,單元測試任然失敗。那么標(biāo)準(zhǔn)庫中的2to3組件能夠自動生成運(yùn)行在python3下的版本焰宣∶骨簦或者Armin Ronacher的python-modernize組件可以用于python2.6+和3.2+或者3.3+(這依賴于命令行輸出參數(shù))。如果你使用python-modernize匕积,同樣需要在Python2下做單元測試盈罐。
任一種方法都可以從單個python2代碼庫并行支持python2和python3。將python2與python3分開維護(hù)更加容易一些闪唆。(可以問問核心代碼開發(fā)者盅粪,他們這么做已經(jīng)很多年了)
如果自動轉(zhuǎn)換后,測試失敗悄蕾,有可能是因?yàn)閜ython3與python2的語義變化票顾。這些變化有可能導(dǎo)致轉(zhuǎn)換器自動轉(zhuǎn)換失敗,-3 switch也沒有檢測出來帆调。這些問題不多奠骄,但是也是存在的。當(dāng)你遇到的時候番刊,提交一個bug給CPython,請求一個新的 -3 警告戚揭,是非常值得的。
如果包含c擴(kuò)展或者工程沒有使用想CPython,cffi,SWIG這些能夠值得處理python2與python3之間的差異的包裹生成器撵枢,移植過程可能更加復(fù)雜民晒。但是還是會比你自己開發(fā)相同功能的包更容易一些。extension porting guide介紹了一些它們之間的主要的不同之處锄禽。
這里是一些比較深入的guide:PortingPythonToPy3k,PortingExtensionModulesToPy3k
我想用python3寫一些東西潜必,但是有些人只用python2,我該怎么辦?
除了有能夠從python2代碼生成python3代碼的2to3工具沃但,還有轉(zhuǎn)換python3代碼到python2代碼的3to2工具磁滚。理論上,可以3to2可能比2to3工作得更好,因?yàn)閜ython3對轉(zhuǎn)換器轉(zhuǎn)換來數(shù)垂攘,清理掉了許多惡心的死角問題(畢竟维雇,盡可能擺脫更多的這種問題是打破向后兼容性的主要原因之一)。然而晒他,那些嚴(yán)重依賴python3特有屬性的代碼(例如函數(shù)注解吱型,擴(kuò)展版tuple unpacking)是不可能轉(zhuǎn)換成功的。
可以舉個恰當(dāng)?shù)谋确剑?to2相對于2to3來說是一條更少旅人的路你可能遇到一些邊邊角角陨仅。如果你想用python3, 這些是值得探索的津滞。
在一些通用模塊代碼中支持python2與python3
python2.6+與python3.3+有大量的相同之處。例如,在python3中對unicode字符串前面加'u'字符的恢復(fù)意味著語義上正確的python2.6+代碼可以與python3.3+兼容灼伤,同時保留著大量的慣用的python触徐。主要的不同是來自不同地方的代碼需要被修改,這樣才可以處理python2與python3之間的命名問題狐赡。
因此撞鹉,six compatibility package是在單一庫中支持python2與python3最主要的實(shí)用程序。
future compatibility package任然在測試中颖侄,并且不像six包一樣支持如此多的python版本(future只支持到python2.6, six可以支持到python2.4)鸟雏。但是future運(yùn)行python2兼容代碼可以寫得跟python3通用代碼一樣的風(fēng)格(例如,它包含了python2兼容python3中bytes類型實(shí)現(xiàn)代碼发皿,而不是依賴于python2中的字節(jié)字符串類型崔慧,他們兩個是不同的API)。
其他一些確定標(biāo)準(zhǔn)庫的主要的因素是是否存在一個更新的對PyPi的移植穴墅,這些移植優(yōu)先用于python2標(biāo)準(zhǔn)庫惶室。下面所列的這些模塊要么是對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ù)者, 對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)庫之間使用玄货,使用移植版本的命名空間模塊可以清楚的指明皇钞。原始版本的屬性可以使用而不會產(chǎn)生沖突。
下面的模塊不是移植版本松捉。但是可以替換標(biāo)準(zhǔn)版本的各個版本兼容的庫夹界。
- requests(對http/https更高級封裝的api)
- regex(一個替代的正則表達(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做選擇的資源
- Community Web site to promote Python 3
- Nick Efford 關(guān)于使用python3教學(xué)的一些點(diǎn)評
- Mark Pilgrim 所寫Python3版的《Dive Into Python》丙者,http://getpython3.com/diveintopython3/
- Swaroop C H 的《A Byte of Python》python3版本,http://www.swaroopch.com/notes/Python
- What an IronPython user should know about Python 3
- Paul Barry的Head First into Python 3
- Mark Summerfield所寫的關(guān)于python2與python3不同的文章:Moving from Python 2 to Python 3
- Wesley Chun所寫的關(guān)于python3的兩篇文章:Python 3: the Evolution of a Programming Language (Mar 2009) 與Python's "New" Division: Python 2 Versus Python 3 (Jan 2010)
- Wesley Chun的Python 3: the Next Generation talk & slides
- James Bennett 的一篇有趣的討論:why Python 3.0 exists at all
- how to get Unicode versus bytes semantics in 2.x similar to the ones in 3.x
- Nick Coghlan 的關(guān)于python3的問答:Q&A
補(bǔ)充說明
- 任然在維護(hù)的包:https://python3wos.appspot.com/
- 主要的linux系統(tǒng)將python鏈接到python3, Ubuntu與Fedora設(shè)置為默認(rèn)值:https://wiki.ubuntu.com/Python/3與https://fedoraproject.org/wiki/Changes/Python_3_as_Default