Python 小技巧:如何實現操做系統兼容性打包?

有一個這樣的問題:現要用 setuptools 把一個項目打包成 whl 文件,而後 pip install 在 Windows/Linux 兩種操做系統上,可是該項目中有一些依賴庫只有 Windows 上纔有(例如 pywinauto、pywingui、pywinrm),那麼問題是,如何實現打包文件的可兼容性安裝?linux

從打包的角度,這個問題的關鍵仍是看 setup.py 和 requirements.txt 文件。git

關於 Python 的包構建分發和 setup.py 的使用,這裏有篇文章 寫得很好,推薦閱讀。另外關於 Python 依賴庫的管理(requirements.txt),這篇文章 詳細比較了 pip、pipreqs、pigar、pip-tools 和 pipdeptree 等工具,也推薦一讀。github

有一個比較笨的實現方法:維護兩份 requirements.txt 文件,分別用來打包,而後分發給不一樣操做系統去使用。macos

可是這樣會有麻煩:維護兩份依賴文件和兩種包文件,自己就挺費勁的,而在生成過程當中,每次還得對它們更名以做區分(注意包名有必定的規範約束,亂改的話,pip 可能識別不出),維護成本就很高。windows

其實,維護軟件包在不一樣操做系統的版本,並很多見。若是你曾留意過不一樣版本 Python 庫文件的話,你會注意到不少庫都會按不一樣操做系統而分發不一樣的版本。例如,下面是同一版本號的 Numpy 在不一樣操做系統上的分發版(https://pypi.org/simple/numpy/):工具

能夠看出它根據 macos、linux 和 win 三類操做系統及其位數,分紅了 5 個版本。維護這麼多版本,確定是一件麻煩事,可是出現了這樣的結果,就意味着 Numpy 官方認爲分發不一樣系統版本是利大於弊的,並且是有辦法實現的。ui

回到咱們的問題,是否有必要像 Numpy 那樣設法打包成多個操做系統定製的包呢?操作系統

答案是否認的。主要的緣由:3d

  • Numpy 這麼作是由於它是作科學計算的,爲了提高效率,它把編譯好的 C 拓展文件打包,從而不須要依賴環境上的 libxxx-devel 之類的庫。若是你編譯安裝過 Python,應該有印象須要安裝 zlib-devel、openssl-devel 和 libffi-devel 之類的系統依賴。但咱們前面的問題比較簡單,並非有不一樣的編譯依賴(系統級),而只是三方庫依賴不一樣(項目級)。
  • 另外一個主要的緣由,Numpy 打包出的不一樣系統版本,並不是簡簡單單地用 setuptools 之類的 Python 庫就能打包,而是要藉助標準的鏡像進行構建。例如,manylinux 版本的打包,參見 Github(https://github.com/pypa/manylinux),就須要使用官方提供的 Docker 鏡像。對於咱們的問題,顯然不想作到這麼麻煩。

簡而言之,根據前面的分析,若是要實現操做系統兼容的打包,維護多份依賴文件、使用不一樣構建包的方法、維護多系統專用的包,方法可行,但並非很適用。日誌

若是沒有新的辦法,這不失爲一種考慮,可是有沒有別的辦法了呢?

我曾被這個問題困擾過,可是沒有深刻去研究解決,直到無心中在loguru 這個用來記錄日誌的庫的 setup.py 中看到:

再翻看大名鼎鼎的requests 庫文件,發現還能夠這樣寫:

兩個示例都是寫在 setup.py 文件中,其實若是咱們用 requirements.txt 文件,也能夠按這種格式寫,而後再讀取進來。

這種神奇的寫法是怎麼回事呢?

它的依據是 2015 年 11 月建立的 PEP-508(以及相關的但已被撤銷或拒絕了的 PEP-390、PEP-42六、PEP-45九、PEP-496),該 PEP 的主要意圖是加強 pip 等工具查找軟件包的能力。

比較重要的部分就是跟咱們的問題相關的,即對操做系統做區分的標識,相關的有:

有了這樣的擴展支持,在打包依賴項時,就能夠解決兼容性問題了。

例如 colorama 庫,若是咱們只在 win32 系統才須要依賴,那麼在打包時就能夠指定:「colorama>=0.3.4 ; sys_platform=='win32' 」;若是不須要限定 win32 系統,而是在 windows 環境都安裝,那麼能夠寫成「colorama>=0.3.4 ; platform_system=='Windows' 」。

最終,咱們解決了本文開頭的問題。這個問題可能比較小衆,解決起來也沒有什麼大文章可作,算是一個小小的 tips 分享給你們吧。

相關文章
相關標籤/搜索