# 目標Python2+3
# 22. 目標Python2+3
很多時候你可能希望你開發的程序能夠同時兼容Python2+和Python3+。
試想你有一個非常出名的Python模塊被很多開發者使用著,但并不是所有人都只使用Python2或者Python3。這時候你有兩個辦法。第一個辦法是開發兩個模塊,針對Python2一個,針對Python3一個。還有一個辦法就是調整你現在的代碼使其同時兼容Python2和Python3。
本節中,我將介紹一些技巧,讓你的腳本同時兼容Python2和Python3。
**Future模塊導入**
第一種也是最重要的方法,就是導入`__future__`模塊。它可以幫你在Python2中導入Python3的功能。這有一組例子:
上下文管理器是Python2.6+引入的新特性,如果你想在Python2.5中使用它可以這樣做:
~~~
from __future__ import with_statement
~~~
在Python3中`print`已經變為一個函數。如果你想在Python2中使用它可以通過`__future__`導入:
~~~
print
# Output:
from __future__ import print_function
print(print)
# Output: <built-in function print>
~~~
**模塊重命名**
首先,告訴我你是如何在你的腳本中導入模塊的。大多時候我們會這樣做:
~~~
import foo
# or
from foo import bar
~~~
你知道么,其實你也可以這樣做:
~~~
import foo as foo
~~~
這樣做可以起到和上面代碼同樣的功能,但最重要的是它能讓你的腳本同時兼容Python2和Python3。現在我們來看下面的代碼:
~~~
try:
import urllib.request as urllib_request # for Python 3
except ImportError:
import urllib2 as urllib_request # for Python 2
~~~
讓我來稍微解釋一下上面的代碼。
我們將模塊導入代碼包裝在`try/except`語句中。我們是這樣做是因為在Python 2中并沒有`urllib.request`模塊。這將引起一個`ImportError`異常。而在Python2中`urllib.request`的功能則是由`urllib2`提供的。所以,當我們試圖在Python2中導入`urllib.request`模塊的時候,一旦我們捕獲到`ImportError`我們將通過導入`urllib2`模塊來代替它。
最后,你要了解`as`關鍵字的作用。它將導入的模塊映射到`urllib.request`,所以我們通過`urllib_request`這個別名就可以使用`urllib2`中的所有類和方法了。
**過期的Python2內置功能**
另一個需要了解的事情就是Python2中有12個內置功能在Python3中已經被移除了。要確保在Python2代碼中不要出現這些功能來保證對Python3的兼容。這有一個強制讓你放棄12內置功能的方法:
~~~
from future.builtins.disabled import *
~~~
現在,只要你嘗試在Python3中使用這些被遺棄的模塊時,就會拋出一個`NameError`異常如下:
~~~
from future.builtins.disabled import *
apply()
# Output: NameError: obsolete Python 2 builtin apply is disabled
~~~
**標準庫向下兼容的外部支持**
有一些包在非官方的支持下為Python2提供了Python3的功能。例如,我們有:
- enum `pip install enum34`
- singledispatch `pip install singledispatch`
- pathlib `pip install pathlib`
想更多了解,在Python文檔中有一個[全面的指南](https://docs.python.org/3/howto/pyporting.html)可以幫助你讓你的代碼同時兼容Python2和Python3。
- 簡介
- 序
- 譯后感
- 原作者前言
- *args 和 **kwargs
- *args 的用法
- **kwargs 的用法
- 使用 *args 和 **kwargs 來調用函數
- 啥時候使用它們
- 調試 Debugging
- 生成器 Generators
- 可迭代對象(Iterable)
- 迭代器(Iterator)
- 迭代(Iteration)
- 生成器(Generators)
- Map和Filter
- Map
- Filter
- set 數據結構
- 三元運算符
- 裝飾器
- 一切皆對象
- 在函數中定義函數
- 從函數中返回函數
- 將函數作為參數傳給另一個函數
- 你的第一個裝飾器
- 使用場景
- 授權
- 日志
- 帶參數的裝飾器
- 在函數中嵌入裝飾器
- 裝飾器類
- Global和Return
- 多個return值
- 對象變動 Mutation
- slots魔法
- 虛擬環境
- 容器 Collections
- 枚舉 Enumerate
- 對象自省
- dir
- type和id
- inspect模塊
- 推導式 Comprehension
- 列表推導式
- 字典推導式
- 集合推導式
- 異常
- 處理多個異常
- finally從句
- try/else從句
- lambda表達式
- 一行式
- For - Else
- else語句
- open函數
- 目標Python2+3
- 協程
- 函數緩存
- Python 3.2+
- Python 2+
- 上下文管理器
- 基于類的實現
- 處理異常
- 基于生成器的實現