很多時(shí)候你可能希望你開(kāi)發(fā)的程序能夠同時(shí)兼容Python2+和Python3+。
試想你有一個(gè)非常出名的Python模塊被很多開(kāi)發(fā)者使用著,但并不是所有人都只使用Python2或者Python3。這時(shí)候你有兩個(gè)辦法。第一個(gè)辦法是開(kāi)發(fā)兩個(gè)模塊,針對(duì)Python2一個(gè),針對(duì)Python3一個(gè)。還有一個(gè)辦法就是調(diào)整你現(xiàn)在的代碼使其同時(shí)兼容Python2和Python3。
本節(jié)中,我將介紹一些技巧,讓你的腳本同時(shí)兼容Python2和Python3。
Future模塊導(dǎo)入
第一種也是最重要的方法,就是導(dǎo)入__future__
模塊。它可以幫你在Python2中導(dǎo)入Python3的功能。這有一組例子:
上下文管理器是Python2.6+引入的新特性,如果你想在Python2.5中使用它可以這樣做:
from __future__ import with_statement
在Python3中print
已經(jīng)變?yōu)橐粋€(gè)函數(shù)。如果你想在Python2中使用它可以通過(guò)__future__
導(dǎo)入:
print
# Output:
from __future__ import print_function
print(print)
# Output: <built-in function print>
模塊重命名
首先,告訴我你是如何在你的腳本中導(dǎo)入模塊的。大多時(shí)候我們會(huì)這樣做:
import foo
# or
from foo import bar
你知道么,其實(shí)你也可以這樣做:
import foo as foo
這樣做可以起到和上面代碼同樣的功能,但最重要的是它能讓你的腳本同時(shí)兼容Python2和Python3?,F(xiàn)在我們來(lái)看下面的代碼:
try:
import urllib.request as urllib_request # for Python 3
except ImportError:
import urllib2 as urllib_request # for Python 2
讓我來(lái)稍微解釋一下上面的代碼。
我們將模塊導(dǎo)入代碼包裝在try/except
語(yǔ)句中。我們是這樣做是因?yàn)樵赑ython 2中并沒(méi)有urllib.request
模塊。這將引起一個(gè)ImportError
異常。而在Python2中urllib.request
的功能則是由urllib2
提供的。所以,當(dāng)我們?cè)噲D在Python2中導(dǎo)入urllib.request
模塊的時(shí)候,一旦我們捕獲到ImportError
我們將通過(guò)導(dǎo)入urllib2
模塊來(lái)代替它。
最后,你要了解as
關(guān)鍵字的作用。它將導(dǎo)入的模塊映射到urllib.request
,所以我們通過(guò)urllib_request
這個(gè)別名就可以使用urllib2
中的所有類(lèi)和方法了。
過(guò)期的Python2內(nèi)置功能
另一個(gè)需要了解的事情就是Python2中有12個(gè)內(nèi)置功能在Python3中已經(jīng)被移除了。要確保在Python2代碼中不要出現(xiàn)這些功能來(lái)保證對(duì)Python3的兼容。這有一個(gè)強(qiáng)制讓你放棄12內(nèi)置功能的方法:
from future.builtins.disabled import *
現(xiàn)在,只要你嘗試在Python3中使用這些被遺棄的模塊時(shí),就會(huì)拋出一個(gè)NameError
異常如下:
from future.builtins.disabled import *
apply()
# Output: NameError: obsolete Python 2 builtin apply is disabled
標(biāo)準(zhǔn)庫(kù)向下兼容的外部支持
有一些包在非官方的支持下為Python2提供了Python3的功能。例如,我們有:
pip install enum34
pip install singledispatch
pip install pathlib
想更多了解,在Python文檔中有一個(gè)全面的指南可以幫助你讓你的代碼同時(shí)兼容Python2和Python3。