摘要
本文將以py3PortScanner為例蝎毡,帶大家了解如何將已經(jīng)完成的python package打包厚柳,在README中添加travis-ci的build passing圖標(biāo),并將package整體上傳至PyPI(Python Package Index)從而使得其他用戶可以通過(guò)pip
命令來(lái)直接安裝這個(gè)package沐兵。
背景知識(shí)需求
本文需要讀者擁有一定的python編程經(jīng)驗(yàn)和開(kāi)源軟件相關(guān)知識(shí)别垮,已經(jīng)了解python package定義并了解如何使用pip進(jìn)行python庫(kù)管理。同時(shí)需要讀者已經(jīng)對(duì)python單元測(cè)試以及軟件測(cè)試有所了解扎谎。
創(chuàng)建生成軟件包所需的文件
首先宰闰,我們需要確保我們的package中已經(jīng)包含了README.md
, LICENSE
和setup.py
文件。三者分別包含該package的說(shuō)明文檔簿透,許可證和python setuptools所用來(lái)安裝該package的構(gòu)建腳本(build script)。
setup.py
setup.py
中包含了該package對(duì)應(yīng)的信息(例如該package的名稱(chēng)解藻,版本老充,作者)以及該package應(yīng)當(dāng)包含的程序文件和數(shù)據(jù)。
參考py3PortScanner的setup.py文件螟左,我們首先讀入了README文件和CHANGELOG文件啡浊。緊著這我們通過(guò)dev_requires
關(guān)鍵字指定了開(kāi)發(fā)環(huán)境所需要的一些依賴(lài)觅够。接著便是最重要的setup()
函數(shù)。在setup函數(shù)中我們指定了該package的作者巷嚣,版本喘先,描述,描述文件格式廷粒,分類(lèi)窘拯,package鏈接(大多數(shù)情況),package所應(yīng)當(dāng)包含的程序文件和數(shù)據(jù)文件坝茎,和程序可以額外安裝的運(yùn)行環(huán)境(需要通過(guò)python3 -m pip install [.dev_requires]
來(lái)安裝)涤姊。同時(shí)在此處還應(yīng)當(dāng)注意另一個(gè)非常重要但在示例中沒(méi)有用到的關(guān)鍵字:install_requires
。該關(guān)鍵字用來(lái)指定當(dāng)前package所依賴(lài)的其他python類(lèi)庫(kù)嗤放。各關(guān)鍵字詳細(xì)含義如下:
-
name
是該package的名字思喊。該名字可以由字母,數(shù)字次酌,_
和-
組成恨课。并且這個(gè)名字不能與其他已經(jīng)上傳至pypi.org的項(xiàng)目相同。 -
version
是當(dāng)前package的版本岳服。關(guān)于版本的詳細(xì)信息請(qǐng)參考PEP440剂公。 -
author
以及author_email
可以用來(lái)指定該package的作者信息。 -
description
對(duì)當(dāng)前package的較短的總結(jié)派阱。 -
long_description
是對(duì)當(dāng)前package的詳細(xì)說(shuō)明诬留。這一詳細(xì)說(shuō)明將被展示在Python Package Index上當(dāng)前項(xiàng)目的主頁(yè),如py3PortScanner主頁(yè)所示贫母。當(dāng)前例子中README的內(nèi)容被直接作為long_description
文兑。這也是一個(gè)常用的方法。 -
long_description_content_type
指定了long_description
內(nèi)容的格式腺劣。在當(dāng)前情況下為markdown绿贞。 -
url
是當(dāng)前package的主頁(yè)鏈接。大多數(shù)情況下這是一個(gè)GitHub, GitLab, Bitbucket或者其他代碼存儲(chǔ)服務(wù)的鏈接橘原。 -
packages
是一系列應(yīng)當(dāng)包含在發(fā)布軟件包文件(distribution package)中的可被import的python包文件籍铁。我們可以手動(dòng)在此處羅列所有文件≈憾希或者如本例中一樣使用find_packages()
函數(shù)自動(dòng)包含所有的python包文件以及子包文件冷溃。 -
classifiers
指定了當(dāng)前package的其他元信息(metadata)杉允。例如當(dāng)前package兼容的python版本和操作系統(tǒng),當(dāng)前package提供的功能的類(lèi)型,當(dāng)前package的許可證等等味赃。我們應(yīng)當(dāng)總是至少包括當(dāng)前package所支持的python版本言秸,操作系統(tǒng)和許可證。注意此處定義的classifiers
關(guān)鍵字所包含的信息應(yīng)當(dāng)符合PyPI的規(guī)定。 -
install_requires
指定了當(dāng)前package所依賴(lài)的其他python類(lèi)庫(kù)糖权。這些指定的python類(lèi)庫(kù)將會(huì)在本package被安裝的時(shí)候一并被安裝。
除去我們此處提到的關(guān)鍵字炸站,尚有很多其他的關(guān)鍵字可以使用星澳。具體可以參考相關(guān)的官方文檔。
README
README文件包含了該python package的詳細(xì)說(shuō)明以及相關(guān)信息旱易。
LICENSE
LICENSE文件指定了當(dāng)前python package的使用許可證禁偎。上傳至Python Package Index的python package應(yīng)當(dāng)包含一個(gè)許可證文件。這一文件指定了使用當(dāng)前python package的用戶應(yīng)當(dāng)遵守怎樣的使用協(xié)議咒唆。關(guān)于如何選擇開(kāi)源軟件許可證届垫,讀者可以參考這一文檔。
使用travis-ci進(jìn)行build test
當(dāng)我們寫(xiě)好相應(yīng)的軟件測(cè)試代碼之后全释,travis-ci可以被用來(lái)對(duì)我們的package進(jìn)行自動(dòng)測(cè)試装处。這一測(cè)試將會(huì)在每一次push時(shí)自動(dòng)運(yùn)行。
.travis.yml
.travis.yml
文件是travis-ci的配置文件浸船,travis-ci將依據(jù)這一配置文件來(lái)創(chuàng)建測(cè)試環(huán)境并運(yùn)行測(cè)試腳本妄迁。具體的配置文檔可以參考travis-ci官方python文檔。
參考py3PortScanner的配置李命,我們逐條分析如下:
-
language
指定了編程語(yǔ)言為python登淘。 -
python
指定了測(cè)試python版本為3.4
,3.5
以及3.6
封字。 -
matrix
用來(lái)指定build相關(guān)的信息黔州,具體可以參考相關(guān)文檔。此處的fast_finish: true
可以使得travis-ci進(jìn)行的build測(cè)試盡可能早地被標(biāo)記為結(jié)束阔籽。 -
install
用來(lái)指定build測(cè)試前用來(lái)安裝所依賴(lài)的python類(lèi)庫(kù)的命令流妻,例如travis-ci官方文檔的這一部分。此處我們使用install: true
來(lái)表示沒(méi)有需要安裝的依賴(lài)庫(kù)笆制。 -
script
用來(lái)指定運(yùn)行測(cè)試的命令或者腳本绅这。此處我們使用了python默認(rèn)的測(cè)試框架,故指定測(cè)試命令為pytest
在辆,既默認(rèn)運(yùn)行所有以test_
開(kāi)頭的測(cè)試文件证薇。詳情可以參考相關(guān)文檔。
使用github賬號(hào)登錄travis-ci.com
打開(kāi)travis-ci網(wǎng)頁(yè)之后匆篓,選擇使用Github賬號(hào)登錄浑度,根據(jù)提示步驟選擇你需要添加travis-ci build測(cè)試的repository并繼續(xù),我們就可以方便地將github repository添加到travis-ci個(gè)人項(xiàng)目中了鸦概。
將測(cè)試圖標(biāo)添加至README
當(dāng)個(gè)人主頁(yè)上對(duì)應(yīng)項(xiàng)目開(kāi)始進(jìn)行built test之后俺泣,我們就可以將build passing圖標(biāo)添加到README中了。步驟如下:
-
點(diǎn)擊頁(yè)面上的build圖標(biāo):
- 在彈出窗口的下拉菜單中選擇相應(yīng)的branch和鏈接格式,例如本例中我們需要master branch的markdown格式的圖標(biāo):
- 將上圖所示的連接直接拷貝到README中伏钠,我們的項(xiàng)目Github主頁(yè)README就有一個(gè)bling bling的build passing圖標(biāo)啦!
生成發(fā)布軟件包文件
當(dāng)我們完成上述步驟后谨设,我們需要打包我們的python package并生成python軟件分發(fā)包(distribution packages)熟掂。這些文件可以被上傳至Python Package Index并由其他用戶通過(guò)pip
命令安裝。
首先我們需要安裝最新版的setuptools
和wheel
扎拣。
python3 -m pip install --user --upgrade setuptools wheel
然后我們運(yùn)行如下命令來(lái)打包程序(確保setup.py
存在于當(dāng)前路徑下)赴肚。
python3 setup.py sdist bdist_wheel
當(dāng)這個(gè)命令運(yùn)行結(jié)束后,確保在生成的dist/
文件夾下存在相應(yīng)的.whl
文件和.tar.gz
文件二蓝。其中.tar.gz
文件是我們的python package的源文件文檔誉券,而.whl
是一個(gè)軟件分發(fā)包(build distribution)。新版本的pip
將會(huì)首先嘗試安裝軟件分發(fā)包刊愚,但在失敗情況下會(huì)接著嘗試采用源文件包安裝踊跟。
將打包好的項(xiàng)目上傳至PyPI
上傳項(xiàng)目
首先我們需要注冊(cè)一個(gè)PyPI的賬號(hào)。如果僅僅為練習(xí)使用鸥诽,則應(yīng)當(dāng)注冊(cè)test.PyPI商玫。任何上傳至test.PyPI的項(xiàng)目將會(huì)在一段時(shí)間之后被刪除。
接著我們需要安裝最新版的twine
牡借。
python3 -m pip install --user --upgrade twine
安裝成功之后我們就可以使用twine來(lái)上傳項(xiàng)目了拳昌。注意在使用twine
上傳項(xiàng)目的時(shí)候需要輸入相應(yīng)的PyPI或test.PyPI的賬號(hào)和密碼。
# 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個(gè)人主頁(yè)上在your projects
欄目下查看我們的項(xiàng)目炬藤。
使用pip
安裝項(xiàng)目
如果我們的項(xiàng)目被上傳至test.PyPI,則需要通過(guò)相應(yīng)的index-url來(lái)安裝碴里。其中的$your_package_name
為我們?cè)?code>setup.py中通過(guò)name
關(guān)鍵字指定的項(xiàng)目名稱(chēng)沈矿。
python3 -m pip install --index-url https://test.pypi.org/simple/ $your_package_name
如果我們的項(xiàng)目被上傳至PyPI,則可以按通常情況直接使用pip
命令和包名稱(chēng)安裝并闲。同樣地细睡,$your_package_name
為我們?cè)?code>setup.py中通過(guò)name
關(guān)鍵字指定的項(xiàng)目名稱(chēng)。
python3 -m pip install $your_package_name
??現(xiàn)在我們就擁有一個(gè)全新的python項(xiàng)目啦帝火!