摘要
本文將以py3PortScanner為例,帶大家了解如何將已經完成的python package打包,在README中添加travis-ci的build passing圖標,并將package整體上傳至PyPI(Python Package Index)從而使得其他用戶可以通過pip
命令來直接安裝這個package。
背景知識需求
本文需要讀者擁有一定的python編程經驗和開源軟件相關知識,已經了解python package定義并了解如何使用pip進行python庫管理。同時需要讀者已經對python單元測試以及軟件測試有所了解。
創建生成軟件包所需的文件
首先,我們需要確保我們的package中已經包含了README.md
, LICENSE
和setup.py
文件。三者分別包含該package的說明文檔,許可證和python setuptools所用來安裝該package的構建腳本(build script)。
setup.py
setup.py
中包含了該package對應的信息(例如該package的名稱,版本,作者)以及該package應當包含的程序文件和數據。
參考py3PortScanner的setup.py文件,我們首先讀入了README文件和CHANGELOG文件。緊著這我們通過dev_requires
關鍵字指定了開發環境所需要的一些依賴。接著便是最重要的setup()
函數。在setup函數中我們指定了該package的作者,版本,描述,描述文件格式,分類,package鏈接(大多數情況),package所應當包含的程序文件和數據文件,和程序可以額外安裝的運行環境(需要通過python3 -m pip install [.dev_requires]
來安裝)。同時在此處還應當注意另一個非常重要但在示例中沒有用到的關鍵字:install_requires
。該關鍵字用來指定當前package所依賴的其他python類庫。各關鍵字詳細含義如下:
-
name
是該package的名字。該名字可以由字母,數字,_
和-
組成。并且這個名字不能與其他已經上傳至pypi.org的項目相同。 -
version
是當前package的版本。關于版本的詳細信息請參考PEP440。 -
author
以及author_email
可以用來指定該package的作者信息。 -
description
對當前package的較短的總結。 -
long_description
是對當前package的詳細說明。這一詳細說明將被展示在Python Package Index上當前項目的主頁,如py3PortScanner主頁所示。當前例子中README的內容被直接作為long_description
。這也是一個常用的方法。 -
long_description_content_type
指定了long_description
內容的格式。在當前情況下為markdown。 -
url
是當前package的主頁鏈接。大多數情況下這是一個GitHub, GitLab, Bitbucket或者其他代碼存儲服務的鏈接。 -
packages
是一系列應當包含在發布軟件包文件(distribution package)中的可被import的python包文件。我們可以手動在此處羅列所有文件。或者如本例中一樣使用find_packages()
函數自動包含所有的python包文件以及子包文件。 -
classifiers
指定了當前package的其他元信息(metadata)。例如當前package兼容的python版本和操作系統,當前package提供的功能的類型,當前package的許可證等等。我們應當總是至少包括當前package所支持的python版本,操作系統和許可證。注意此處定義的classifiers
關鍵字所包含的信息應當符合PyPI的規定。 -
install_requires
指定了當前package所依賴的其他python類庫。這些指定的python類庫將會在本package被安裝的時候一并被安裝。
除去我們此處提到的關鍵字,尚有很多其他的關鍵字可以使用。具體可以參考相關的官方文檔。
README
README文件包含了該python package的詳細說明以及相關信息。
LICENSE
LICENSE文件指定了當前python package的使用許可證。上傳至Python Package Index的python package應當包含一個許可證文件。這一文件指定了使用當前python package的用戶應當遵守怎樣的使用協議。關于如何選擇開源軟件許可證,讀者可以參考這一文檔。
使用travis-ci進行build test
當我們寫好相應的軟件測試代碼之后,travis-ci可以被用來對我們的package進行自動測試。這一測試將會在每一次push時自動運行。
.travis.yml
.travis.yml
文件是travis-ci的配置文件,travis-ci將依據這一配置文件來創建測試環境并運行測試腳本。具體的配置文檔可以參考travis-ci官方python文檔。
參考py3PortScanner的配置,我們逐條分析如下:
-
language
指定了編程語言為python。 -
python
指定了測試python版本為3.4
,3.5
以及3.6
。 -
matrix
用來指定build相關的信息,具體可以參考相關文檔。此處的fast_finish: true
可以使得travis-ci進行的build測試盡可能早地被標記為結束。 -
install
用來指定build測試前用來安裝所依賴的python類庫的命令,例如travis-ci官方文檔的這一部分。此處我們使用install: true
來表示沒有需要安裝的依賴庫。 -
script
用來指定運行測試的命令或者腳本。此處我們使用了python默認的測試框架,故指定測試命令為pytest
,既默認運行所有以test_
開頭的測試文件。詳情可以參考相關文檔。
使用github賬號登錄travis-ci.com
打開travis-ci網頁之后,選擇使用Github賬號登錄,根據提示步驟選擇你需要添加travis-ci build測試的repository并繼續,我們就可以方便地將github repository添加到travis-ci個人項目中了。
將測試圖標添加至README
當個人主頁上對應項目開始進行built test之后,我們就可以將build passing圖標添加到README中了。步驟如下:
-
點擊頁面上的build圖標:
build圖標 - 在彈出窗口的下拉菜單中選擇相應的branch和鏈接格式,例如本例中我們需要master branch的markdown格式的圖標:
markdown build圖標鏈接 - 將上圖所示的連接直接拷貝到README中,我們的項目Github主頁README就有一個bling bling的build passing圖標啦!
生成發布軟件包文件
當我們完成上述步驟后,我們需要打包我們的python package并生成python軟件分發包(distribution packages)。這些文件可以被上傳至Python Package Index并由其他用戶通過pip
命令安裝。
首先我們需要安裝最新版的setuptools
和wheel
。
python3 -m pip install --user --upgrade setuptools wheel
然后我們運行如下命令來打包程序(確保setup.py
存在于當前路徑下)。
python3 setup.py sdist bdist_wheel
當這個命令運行結束后,確保在生成的dist/
文件夾下存在相應的.whl
文件和.tar.gz
文件。其中.tar.gz
文件是我們的python package的源文件文檔,而.whl
是一個軟件分發包(build distribution)。新版本的pip
將會首先嘗試安裝軟件分發包,但在失敗情況下會接著嘗試采用源文件包安裝。
將打包好的項目上傳至PyPI
上傳項目
首先我們需要注冊一個PyPI的賬號。如果僅僅為練習使用,則應當注冊test.PyPI。任何上傳至test.PyPI的項目將會在一段時間之后被刪除。
接著我們需要安裝最新版的twine
。
python3 -m pip install --user --upgrade twine
安裝成功之后我們就可以使用twine來上傳項目了。注意在使用twine
上傳項目的時候需要輸入相應的PyPI或test.PyPI的賬號和密碼。
# upload to test PyPI
python3 -m twine upload --repository-url https://test.pypi.org/legacy/ dist/*
# upload to real PyPI
python3 -m twine upload dist/*
上傳完畢后,我們就可以前往PyPI個人主頁上在your projects
欄目下查看我們的項目。
使用pip
安裝項目
如果我們的項目被上傳至test.PyPI,則需要通過相應的index-url來安裝。其中的$your_package_name
為我們在setup.py
中通過name
關鍵字指定的項目名稱。
python3 -m pip install --index-url https://test.pypi.org/simple/ $your_package_name
如果我們的項目被上傳至PyPI,則可以按通常情況直接使用pip
命令和包名稱安裝。同樣地,$your_package_name
為我們在setup.py
中通過name
關鍵字指定的項目名稱。
python3 -m pip install $your_package_name
??現在我們就擁有一個全新的python項目啦!