如何為 Linux 打包 Python 應用

2020-04-23 23:55:00

了解如何使用 dh_virtualenv 來讓你的 Python 應用可作為 .deb 包安裝。

在基於 Debian 的作業系統(例如 Debian 或 Elementary OS)上安裝 Python 應用的一種方法是使用 dh_virtualenv 工具。它可以構建一個 .deb 包,在應用之外封裝了一個 Python 虛擬環境,並在安裝時進行部署。

在本文中,我將以構建一個包含 HTTPie 工具的包為例來解釋如何使用它,以便在無需啟用虛擬環境的情況下從命令列測試 HTTP API。

使用 dh_virtualenv 打包

首先,你需要安裝 dh_virtualenv 所需的工具。dh_virtualenv文件提供了所有安裝選項。在基於 Debian 的系統上,我輸入:

apt-get install dh-virtualenv devscripts

儘管不需要 devscripts 包,但它可以簡化後續操作。

現在,建立一個目錄來儲存原始碼。由於這是一個原生的、非官方的 HTTPie 打包,因此我將其稱為 myhttp。接下來,讓我們在 myhttp 內建立一些檔案,向 Debian 構建系統提供後設資料。

首先,建立 debian/control 檔案:

Source: myhttpSection: pythonPriority: extraMaintainer: Jan Doe <[email protected]>Build-Depends: debhelper (>= 9), python3.7, dh-virtualenv (>= 0.8)Standards-Version: 3.9.5Package: myhttpArchitecture: anyPre-Depends: dpkg (>= 1.16.1), python3.7, ${misc:Pre-Depends}Depends: ${misc:Depends}Description: http client Useful for doing stuff

那麼這些是什麼資訊呢?正如 Debian 文件指出的:

“第 1–7 行是原始碼包的控制資訊。第 9–13 行是二進位制包的控制資訊。”

以下是我使用的:

  • Section 的值對於我們來說大多沒有意義,但需要存在。它對給引導式 UI 安裝程式提供資訊是有意義的,但對於這個包來說,沒有意義。
  • Priority 對像這樣的第三方包的正確值是 extra
  • 強烈建議在 Maintainer 欄位中填寫正確的聯絡人資訊。但不一定非得是你的個人電子郵件,如果包由團隊維護,並且你希望將問題傳送到團隊的郵件別名,例如 Infrastructure Team <[email protected]>
  • Build-Depends 欄位標識你需要 debhelperpythondh-virtualenv 來構建包:包構建過程中將確保這些依賴項在包構建時已安裝。
  • Standards-Version 欄位主要給人看。它表明你遵循的指南。本指南基於 dh-virtualenv 的官方文件,它是基於 Debian 的 3.9.5 指南。最好一直將原始碼包和二進位制包命名相同。
  • Architecture 欄位應為 Any,因為除非虛擬環境可能包含一些特定於體系結構的檔案。否則,最好選擇該欄位為 any
  • 保持 Pre-Depends 列表不變:它是一種非常嚴格的依賴關係形式,你很少會需要比這裡建議的最小依賴更多的依賴項。依賴項通常由構建系統準確計算,因此沒有理由手動指定它們。
  • 如果你的包主要用於內部,那麼 Description 欄位可能只需要最少的資訊或者指向公司 wiki 的連結,不然更多的資訊會更有用。

然後建立 debian/compat 檔案,它主要出於歷史目的而存在

$ echo "9" > debian/compat

接下來,建立更新紀錄檔以告知包使用者自上次發布以來發生了什麼變化。最簡單的方法是使用 dch --create 建立模板,然後填寫值。

填寫後,它看起來像:

myhttp (2.0.0-1) stable; urgency=medium  * Initial release. -- Jan Doe <[email protected]>  Fri, 27 Mar 2020 01:09:22 +0000

現在你需要告訴工具安裝 HTTPie,但是哪個版本?

建立一個寬鬆版本的 requirements.in 檔案:

httpie

通常,寬鬆的需求檔案將僅包含專案的直接依賴項,並在需要時指定最低版本。不一定總是需要指定最低版本:這些工具通常偏向於將依賴關係轉化為“可能的最新版本”。如果你的 Debian 包與一個內部 Python 包相對應,這是內部應用中的一種常見情況,那麼寬鬆的需求檔案看起來將很相似:僅包含包名的一行。

然後使用 pip-compile(可通過安裝 PyPI 包 pip-tools 獲得):

$ pip-compile requirements.in > requirements.txt

這會生成一個嚴格的依賴檔案,名為 requirements.txt

## This file is autogenerated by pip-compile# To update, run:##    pip-compile requirements.in#certifi==2019.11.28       # via requestschardet==3.0.4            # via requestshttpie==2.0.0             # via -r requirements.inidna==2.9                 # via requestspygments==2.6.1           # via httpierequests==2.23.0          # via httpieurllib3==1.25.8           # via requests

最後,寫一個 debian/rules 檔案來建立包。因為 dh_virtualenv 會處理所有困難的事,因此規則檔案很簡單:

#!/usr/bin/make -f%:        dh $@ --with python-virtualenv --python /usr/bin/python3.7

確保指定 Python 直譯器。預設它會使用 /usr/bin/python,這是 Python2,但是你應該使用一個受支援的 Python 版本

完成了,接下來就是構建包:

$ debuild -b -us -uc

這會在父目錄生成一個類似 myhttp_2.0.0-1_amd64.deb 的檔案。該檔案可在任何相容的系統上安裝。

通常,最好在同一平台上構建用於特定平台(例如 Debian 10.0)的 Debian 包。

你可以將此 Debian 包儲存在軟體倉庫中,並使用例如 Ansible 的工具將其安裝在所有相關系統上。

總結

給基於 Debian 的系統的打包應用是一個有著多個步驟的過程。使用 dh_virtualenv 將使過程變得簡單明瞭。