注意,本文內容基於python 2。python 3的處理方式可能有所不一樣,有須要的讀者能夠本身瞭解一下。python
wheel 包的命名格式爲 {distribution}-{version}(-{build tag})?-{python tag}-{abi tag}-{platform tag}.whl
。
其中各個 tag 的意義和取值在 PEP425 中有規定:https://www.python.org/dev/pe...linux
python tag 標記了具體的 python 實現。其中:架構
py 無實現特定的拓展python2.7
cp CPython,也就是一般使用的 Python 實現ide
ip IronPython,跑在 Windows CLI 平臺上的 Python 實現ui
pp PyPy,帶 JIT 的 Python 實現操作系統
jy Jython,跑在 JVM 上的 Python 實現debug
舉個例子,若是 wheel 包裏面包含了 C 拓展,那麼打包出來的 python tag 就是 cpxx,其中 xx 是具體的版本號,如 cp27.code
platform tag 也好理解,就是系統 _ 架構。好比 linux_x86_64
。orm
最陌生的恐怕是之間的 abi tag,這正是本文討論的主題。
abi 這東西,看不見摸不着。系統上的東西嘛,敲下個命令就知道是什麼操做系統;架構雖然玄乎點,不過也就是那麼幾種;然而有多少人知道本身當前使用的平臺遵循着怎樣的 abi 標準?何時 abi 能夠兼容,何時又不能夠?
Python 對此有另一個 PEP:https://www.python.org/dev/pe...
若是 sysconfig
定義了 SOABI
,那麼就用 SOABI
的值。固然這是 Python 3 的事務,這裏我天然不用管。若是沒定義 SOABI
,好比 Python 2,wheel 會生成一個相似的 abi tag。在 Python 的標準裏,這個 abi 取決於打包時使用的 Python 實現。舉 CPython 爲例,首先必須包含的是實現名和版本號,好比 CPython2.7.9 對應的是 cp27.其次,須要包含構建 CPython 時特定的選項。具體來講,打包時會依次判斷當前的 CPython 是否有下列的功能,若是有,加上對應的 flag:
--with-pydebug (flag: d )
--with-pymalloc (flag: m )
--with-wide-unicode (flag: u )
一般,咱們看到的 abi tag 會是這樣的 cp27mu
,這是由於 --with-pymalloc
是默認開啓的,而包管理中分發的 CPython 會加上 --with-wide-unicode
選項。
有趣的是,若是打包時沒辦法判斷 abi 類型,生成的 abi tag 會是 none
。而若是 Python 包是不依賴特定的 abi 的純 Python 實現,生成的 abi tag 也是 none
。在安裝時,值爲 none
的 abi tag 會享受特殊待遇。這個下文再說。
另外一樣的 Python 代碼打出來 abi tag 相同的包,不必定徹底同樣。以個人親身經歷舉例,pycrypto
這個庫,在打包的時候會判斷 libgmp
是否存在,若是存在,就構建 _fastmath
這個庫。若是打包平臺上存在 libgmp
,打出來的包就會包含 _fastmath
。反之,則不存在。而這兩種情形下打出來的包,名字是如出一轍的。
一般判斷依賴的時候,須要看下是否符合最低版本。不過 pip 判斷給定 wheel 包的 abi 兼容的作法與此有些許差別。pip 的作法是,計算出一個支持的 abi tag 集合,而後判斷目標 abi tag 是否在這個集合裏。這個計算過程跟在打包時是同樣的。這意味着,打包拓展的 CPython 須要跟安裝的機器上的 CPython 版本是一致的,不然就裝不了。對於「永遠的2.7」來講,這不是什麼問題;不過若是用的是 Python 3,又不能控制具體的 CPython 版本,對於 C 拓展仍是現場編譯安裝比較靠譜。
其實說了這麼多,還不如跑一個腳本:
/usr/local/lib/python2.7/site-packages/pip/pep425tags.py
pip 會運行這個腳原本判斷 wheel 包。因此你只要
from pip import pep425tags print(pep425tags.get_supported())
就能報出該系統上支持的 wheel 包名字。
固然對於 abi tag 爲 none
的包,它能夠在任何一個 abi 版本上安裝。由於全部的平臺都至少支持 none
abi。但若是一個平臺上的 Python 如此古怪,以至於沒辦法肯定它的 abi 類型,那麼也就只能裝上 abi tag 爲 none
的包,即純 Python 實現抑或一樣古怪得沒法判斷打包時的 abi 的包。真是同類相聚啊。順便一提,在 Ubuntu 14.04 和同期的系統,經過包管理安裝的 pip 有一個已知 bug,有些時候沒法正確判斷 abi 類型,因此打出來的包的 tag 是 none
,且任何帶特定 abi 的包都裝不上去。咱們曾經遇到這個 bug,最後經過升級 pip 解決了。感興趣的讀者能夠比較這包管理版本和最新版本,兩個 pip 的 pep425tags.py 有什麼異同。