python pip 打包指南

一個成功的開源項目的其核心功能是打包功能,而出色的打包功能的關鍵在於版本控制。因爲項目是開源的,所以您希望發佈的包能夠體現出開源社區所具備的優點。不同的平臺與語言具有不同的打包機制,本文主要講述的是 Python 及其打包機制。本文所討論的打包機制可以作爲您的基礎學習,此外還提供了大量的實例,可讓您快速起步。

關注打包的理由

除了正確做法這條理由之外,打包軟件還有三條實際的理由:

  • 易用性
  • 穩定性(帶有版本控制)
  • 發佈

儘量減少用戶安裝您的應用程序的工作量是值得的。打包會讓您的軟件變得更容易訪問和安裝。如果其安裝流程更加簡便,用戶就會更加願意使用您的軟件。如果在 Python Package Index (PyPI) 上發佈您的包,那麼就可以通過像 pip 或 easy_install 這樣的實用工具輕易地對其進行訪問。請參見 參考資料 中的鏈接,以瞭解關於這些工具的更多信息。

另外,通過對包進行版本控制,可以指定用戶的項目依賴於某一個特定版本。例如,將 Pinax 指定爲 0.9a2.dev1017 版本,表達如下:

Pinax==0.9a2.dev1017

這樣就會強制項目使用 0.9a2.dev1017 版本的 Pinax。

如果您稍後發佈可能破壞接口的軟件變更,版本控制會保證更好的穩定性。它允許用戶確切地瞭解他們獲得了什麼,並使跟蹤版本之間差異的工作變得更加輕鬆。此外,項目開發人員可以確切地知道他們正在基於什麼進行編碼。

將包發佈到 PyPI(或者您自己的發佈服務器)上的一種常用方法是創建一個源發佈並上傳。源發佈是將項目源代碼打包爲一個可發佈單元的一種標準方式。創建二進制發佈有多種途徑,但是爲了開源,發佈源代碼也合乎情理。創建源發佈可充許人們能夠輕易地使用工具,在 Internet 上查找和下載軟件並執行全自動軟件安裝。此過程不僅有助於本地開發,而且對軟件的部署也有助益。

因此,通過讓用戶能夠更加輕鬆地集成與安裝您的軟件,使用支持可靠固定技術的優秀版本控制,併發布您的包以實現更好的分佈,您項目取得成功並獲得廣泛採用的機會就將大增。更廣泛的採用意味着更多的參與者,這想必是每一位開源開發人員的希望。

setup.py 文件的剖析

setup.py 腳本的用途之一是充當可執行文件,您可以運行它來打包軟件並將其上傳到發佈服務器上。當您瀏覽流行的 Python 庫時,setup.py 腳本的內容可能存在相當大的差異。本文主要關注於基礎知識。如想進一步瞭解,請參見 參考資料 部分的內容。

setup.py 文件有多種用途,但在這裏創建它的目的是運行以下命令:

python setup.py register
python setup.py sdist upload

第一個命令 register 使用 setup.py 腳本中 setup() 函數提供的信息,併爲您的包在 PyPI 上創建了一個入口。它不會上傳任何內容,相反它會創建關於項目的元數據,以便您能夠隨後上傳與保存版本。接下來的兩個命令是串連在一起使用的:sdist upload 構造了一個源發佈,然後將它上傳到 PyPI。但是有一些先決條件,比如要設置您的 .pypirc 配置文件並實際寫入 setup.py 的內容。

首先配置 .pypirc 文件,該文件應該位於您的主目錄(根據操作系統的不同而有所變化)中。在 UNIX®、Linux® 與 Mac OS X 上,輸入 cd ~/即可訪問該目錄。該文件的內容應該包含您的 PyPI 證書,如 清單 1 中所示。

清單 1. 典型的 .pypirc 文件
[distutils]
index-servers =
    pypi

[pypi]
username:xxxxxxxxxxxxx
password:xxxxxxxxxxxxx

接下來,訪問 PyPI 並註冊一個賬號(不用擔心,它是免費的)。將您在 PyPI 上創建的用戶名與密碼放入 .pypirc 文件中,並確保文件名爲~/.pypirc。

在編寫 setup.py 腳本時,您必須決定要在 PyPI 索引頁面上顯示什麼內容,以及您想給項目取什麼名稱。從複製我對項目使用的 setup.py 模板開始(參見清單 2)。跳過導入與函數,查看模板末端,看看需要修改什麼地方來適應您的項目。請參見 參考資料 中關於完整腳本的鏈接。

清單 2. setup.py 模板
PACKAGE = ""
NAME = ""
DESCRIPTION = ""
AUTHOR = ""
AUTHOR_EMAIL = ""
URL = ""
VERSION = __import__(PACKAGE).__version__

setup(
    name=NAME,
    version=VERSION,
    description=DESCRIPTION,
    long_description=read("README.rst"),
    author=AUTHOR,
    author_email=AUTHOR_EMAIL,
    license="BSD",
    url=URL,
    packages=find_packages(exclude=["tests.*", "tests"]),
    package_data=find_package_data(
			PACKAGE,
			only_in_packages=False
	  ),
    classifiers=[
        "Development Status :: 3 - Alpha",
        "Environment :: Web Environment",
        "Intended Audience :: Developers",
        "License :: OSI Approved :: BSD License",
        "Operating System :: OS Independent",
        "Programming Language :: Python",
        "Framework :: Django",
    ],
    zip_safe=False,
)

首先要注意,這個模板希望您的項目具有兩個不同文件。第一個文件用於 long_description,它讀取與 setup.py 位於同一目錄中的 README.rst 文件的內容,並將內容以字符串形式傳遞給 long_description 參數。此文件用於填充 PyPI 上的登錄頁面,因此在文件中簡要描述項目並顯示一些使用實例是個好主意。第二個文件是包的 __init__.py 文件。這裏並沒有明確提及它,但設置 VERSION 變量的行用於導入了您的包。而當執行此項操作時,Python 還需要一個 __init__.py 文件和一個在該模塊中定義的名爲 __version__ 的變量。就目前而言,只要將它設置爲一個字符串即可:

# __init__.py
__version__ = "0.1"

現在,讓我們看一看其餘的輸入:

  • PACKAGE 是您項目中的 Python 包。它是頂級文件夾,其中包含應該與 setup.py 文件位於相同目錄中的 __init__.py 模塊,例如:
    /-
      |- README.rst
      |- setup.py
      |- dogs 
         |- __init__.py
         |- catcher.py

    因此,這裏的 dogs 就是您的包。

  • NAME 一般類似或等同於您的 PACKAGE 名稱,但可以是您希望的任何內容。NAME 就是人們引用您的軟件時使用的名稱,這個軟件名稱將會列在 PyPI 中,而且更重要的是,用戶將使用這個名稱來安裝軟件(例如,pip 安裝 NAME)。
  • DESCRIPTION 只是對您的項目的一段簡要描述,一句話便已足夠。
  • AUTHOR 與 AUTHOR_EMAIL 正如它們字面上的意思:您的姓名和電子郵件地址。這些信息是可選的,但提供電子郵件地址是比較實際的做法,因爲人們可能希望與您取得聯繫。
  • URL 是項目的 URL。這個 URL 可能是一個項目網站、Github 庫或您希望的任意 URL。再次強調,這些信息是可選的。

您可能還希望提供許可證與分類。瞭解有關創建一個 setup.py 文件的更多信息,請參考 Python 文檔。請參見 參考資料)。

版本控制

版本控制本身就是一個很大的主題,但在打包時不得不提到它,因爲優秀的打包需要正確的版本控制。 版本控制是您與用戶進行某種形式的溝通:它也允許用戶在其產品中實現更好的穩定性與可靠性。通過版本控制,您可以告訴用戶您修改了哪些內容,併爲這些修改出現的位置設定明顯的界限。

在 Python Enhancement Proposal (PEP) 386 中可以找到對 Python 包進行版本控制的一種標準(請參見 參考資料)。它給出了一些實用的規則。即使您沒有閱讀和理解或者甚至是贊同 PEP,最好也按照它來行事,因爲越來越多的 Python 開發人員已經習慣於這樣做。

另外,版本控制不僅用於您上傳到 PyPI 上的穩定版本,而且還用於使用 devNN 後綴的開發版本。將這些開發版本上傳到 PyPI 上通常不太好,但您可以通過設置自己公共的(或私有的)發佈服務器,讓它們變爲可公共訪問的。然後,想使用最新版本的用戶就可以在他們的 pip 需求 .txt 文件中進行引用。下面給出了版本控制的一些例子:

1.0.1        # 1.0.1 final release
1.0.2a       # 1.0.2 Alpha (for Alpha, after Dev releases)
1.0.2a.dev5  # 1.0.2 Alpha, Dev release #5

發佈

如果沒有發佈,人們一般無法找到和安裝您的軟件。大多數時候,您需要把自己的包發佈到 PyPI 上。在設置 .pypirc 配置文件之後,您傳遞給 setup.py 的 upload 命令將把您的包傳輸給 PyPI。通常,您在這樣做的同時還會構建一個源發佈:

python setup.py sdist upload

如果您使用的是自己的發佈服務器,而且 .pypirc 文件中的授權部分也包含了這個新位置,只要在上傳時引用它的名稱即可:

python setup.py sdist upload -r mydist

搭建您自己的發佈服務器

在開源環境中使用自己的發佈服務器的主要原因是提供一個發佈開發版本的位置,因爲 PyPI 實際上只應該包含穩定的版本。例如,您很可能想使用如下命令:

pip install MyPackage

安裝從 PyPI 上發現的最新穩定版本。然而,如果您添加後來的開發版本,該命令會結束最新版本的安裝,也就是您的開發版本。固定版本始終是正確的做法,但並非所有的用戶都能堅持這麼做。因此,確保在指定版本號時總是返回最新的穩定版本。

一種兩全其美的方法(只對 pip 的默認用法公開穩定的版本,同時允許用戶安裝打包的開發版本)是使用自己的發佈服務器。Pinax 項目爲它所有的開發版本都做了這項工作,網址是 http://dist.pinaxproject.com(參見 參考資料)。

發佈服務器只是一個索引,基於 Hypertext Transfer Protocol (HTTP) 協議爲服務器上的文件提供服務。它的文件結構應該如下:

/index-name/package-name/package-name-version.tar.gz

通過在 Web 服務器上配置 Basic-Auth,您可以將服務器變爲私有。您可能還想添加一些工具來上傳源發佈。爲此,需要添加代碼來處理上傳,解析文件名,以及創建與上述模式相匹配的目錄路徑。這種結構在 Pinax 項目中已經開始應用,該項目擁有幾個庫。

pip 與 virtualenv

儘管本文的講述重點是打包,這部分內容描述瞭如何使用包,以及優秀的打包與版本控制爲用戶能夠帶來的好處。

pip 是可以直接安裝的工具,但我建議使用它作爲 virtualenv 的一部分(參見 參考資料)。我建議對與 Python 相關的所有內容均使用virtualenv,因爲它可以保持 Python 環境的乾淨。正如一臺虛擬機允許同時運行多個操作系統一樣,virtualenv 也支持您同時運行多個 Python 環境。我沒有在我的系統 Python 中安裝任何內容,而是爲我使用的每個新項目或實用工具都創建了一個新的 virtualenv

安裝 virtualenv 後,立即就可以使用:

$ mkvirtualenv —no-site-packages testing
$ pip install Pinax
$ pip freeze|grep Pinax
$ pip uninstall Pinax
$ pip install —extra-index-url=http://dist.pinaxproject.com/fresh-start/ 
    Pinax==0.9a2.dev1017
$ pip freeze|grep Pinax

注意,第一個 pip 安裝是從 PyPI 下載和安裝的。pip freeze 可以顯示當前 virtualenv 中已安裝的所有包版本。pip uninstall 的用途與您猜想的完全一樣:將它自己從 virtualenv 中刪除。接下來,您要在全新的庫中安裝一個開發版本,地址是 http://dist.pinaxproject.com,以便獲取 Pinax 0.9a2.dev1017 版的開發版本。

無需訪問網站,下載 tarball,並將代碼與網站包建立符號鏈接(這是我通常的做法,會引發很多問題)。用戶只有在項目中實現優秀的打包、發佈與版本控制,才能做到這一切。

結束語

總的說來,您花費一些時間來學習打包的藝術與科學是值得的。由於對包進行版本控制會帶來易安裝性和穩定性,所以您的軟件會被更多用戶採用。使用 參考資料 和本文所提供的模板 setup.py,您可以快速而方便地給項目增加打包功能。通過正確的版本控制與用戶溝通,站在用戶的角度去考慮,可以讓他們更容易跟蹤版本之間的變化。最後,由於 pip 與 virtualenv 贏得了更爲廣泛的採用,對發佈包的依賴(位於 PyPI 或您自己的發佈服務器上)越來越大。因此,一定要發佈你想要與全世界分享的項目。

我希望本文爲您提供了足夠多的基礎知識。參考資料 將提供更多相關文檔以供您進行進一步的瞭解。如有疑問,請到 Freenode、聊天室 #pinax and #django-social(我暱稱叫 “paltman”)或 Twitter 上與我交流。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章