全文共7134字,預計學習時長14分鐘html
假設你很喜歡用同一段Python代碼,裏面有幾個相關的小型函數,或者是含有幾百行代碼的中型模塊。程序員可能會把它複製到不一樣的項目或存儲庫中,或者從特別設置的實用工具代碼文件夾中導入這段代碼。python
這很正常。程序員在編寫代碼的過程當中都會不斷積累這些個性化的小工具。相比其餘編程語言來講,Python更容易積累這些語句——這些代碼很是實用。git
若是無需複製,就能夠輕鬆導入本身開發的小工具,並進行更新和維護,豈不是更好嗎?若是不依賴於特定的文件或路徑,讓這些代碼在不一樣的環境、機器和語境中都適用?若是能夠將這些個性化工具版本化,並使相關代碼清楚地反映出其依賴性呢?若是這個工具能爲大衆所用呢?程序員
沒錯,它均可以作到。github
固然,這個概念不是第一次提了。這就是一般在編程語言中使用模塊、包和庫的緣由,特別是在Python的開發環境中。它的實現可以使Python功能更增強大;只需簡單的pip install 和 import就能得到BeautifulSoup的html解析功能或pandas的數據幀處理功能。面試
另外,人人均可以將本身的代碼在PyPI上編寫和發佈(PyPI是Python包的官方索引:http://pypi.python.org/pypi),使它們與sklearn、requests或delorean(都是很是實用、流行的Python包)同樣簡單易得。如下是它的幾點優點:django
· 即便只有不多人使用,共享本身的代碼還是一件頗有趣的事;程序員能夠在工做、社羣活動或求職面試中分享並展現本身的勞動成果。編程
· 經過強制性地整理和記錄代碼,公開給同行進行評價,從而改進代碼。flask
· 它還能彌補社羣的不足。你會驚訝地發現,不少人會注意到你的序列化十分高效,好比將HTTP報頭序列化到JSON。或者發現本身建立的用來驗證輸入MongoDB查詢文檔修飾符的工具備多麼實用。數組
心動了嗎?忘記那個舊的Python模塊,開始製做小型Python包吧。
圖1: Python dust
首先是命名。好的名字一般比較簡短,便於在pip install 或 import 完成以後輸入(儘管如今已經出現了「自動輸入」);還要包含足夠的信息便於理解,或者在安裝完成後以後提示其中的內容。
requests負責處理HTTP請求、delorean負責日期和時間,sklearn負責提供機器學習框架,這些都是很好的例子。在爲pandas管道包(因爲pandas 一般以pd這樣較短別名導入,故使用pdpipe:https://github.com/shaypal5/pdpipe)和緩存包(cachier:https://github.com/shaypal5/cachier)命名時,筆者也嘗試過這些例子。
不過老實說,這些並非固守的規則。流行的Python包都有pandas、 keras、 django、 boto、 jinja、 flask 和 pytorch等名稱,你們能記住這些名字,因此讀者也可使用任何簡短且可讀的名稱(例如,因爲可讀性問題,筆者將「Scikit-Learn Wrappers for FastText」縮寫成了skift)。本文以chocobo爲例。
步驟二:肯定代碼包的基本結構
接下來,經過幾個簡短的步驟,製做一種通用的結構:
1.用代碼包的準確名稱建立一個Github存儲庫,不要使用駝峯式或過多的我的發揮。而後在本地進行復制。
2.在該存儲庫中新建一個文件夾,用代碼包的準確名稱命名;這就是保存代碼包的文件夾。這是一種規範,只需記住外部的chocobo 文件夾(在本例中)就是存儲庫的文件夾,而內部的chocobo 文件夾是包的文件夾。
3.將本身的模塊和涉及到的任何其餘模塊放在內部的chocobo文件夾中。若是存在缺失的部分,請添加__init__.py 文件。
4.將用戶直接調用的重要對象(一般是函數)從各自的模塊中導入至__init__.py文件。有了代碼包的命名空間,就可使用這些函數、分類和變量了。若是願意,也可使用代碼包的API。
5.雖然不是強制規定,筆者強烈建議在代碼包或在存儲庫的根目錄中都應包含一個 .gitignore 文件。
示例:https://github.com/github/gitignore/blob/master/Python.gitignore
如今有了一個結構,能夠添加不一樣類型的文件組成代碼包;內部文件夾保存的是包的代碼,外部文件夾保存的是輔助包文件和其餘與存儲庫相關的文件。
所以,初始模塊chocobo.py以下所示:
"""My chocobo cooking script."""
import os
def chocobo_roast(num_guests, hotness_level):
# amazing python code here複製代碼
新建存儲庫文件夾以下所示:
chocobo/
chocobo/
__init__.py
chocobo.py
.gitignore複製代碼
__init__.py 文件應以下所示:
"""chocobo is a python package for delicious Chocobo recipes."""
from .chocobo import (
chocobo_roast,
)複製代碼
那麼在完成封裝以後,chocobo包能夠有這樣的使用方法:
"""I'm a script or a different package using chocobo."""
import chococbo
def my_feast(num_guests):
snacks = bobbish()
main_course = chocobo.chocobo_roast(num_guests, 0)
dressing = szechuan_chicken_mcnugget_sauce()複製代碼
以上就是一些要點。
步驟三:許可問題
使用共享許可發佈代碼是較爲可取的;若是要將本身的代碼公開分享,程序員會想要在保留版權的前提下獲得重用代碼的許可,或者讓那些擴展本身代碼的人保證衍生代碼能夠自由使用。得到許可能輕鬆解決這些問題。
對於無足輕重的小項目,能夠考慮MIT許可(https://choosealicense.com/licenses/mit/)。choosealicense.com(https://choosealicense.com/)提供了不少GitHub和開源社區中的實用建議。
不管選擇哪一種許可,都比根本不用要好。不少時候,在沒有許可的狀況下公開代碼還不如不公開;若是程序員不明確本身對代碼的全部權,大多數公司會由於可能形成的法律糾紛而放棄,從而失去許多潛在用戶。
選擇許可後,在存儲庫中建立LICENSE許可文件(不須要文件擴展名),並導入所選許可的確切文本。
步驟四:安裝文件
如今建立Python封裝工具所需的基本文件(以setuptools爲例);setup.py.setup.py 包含了構建和發行時使用的實際指令。
下面是一個初始模板(別擔憂,稍後會進行詳細檢查)
"""Setup for the chocobo package."""
import setuptools
with open('README.md') as f:
README = f.read()
setuptools.setup(
author="Shay Palachy",
author_email="shay.palachy@gmail.com",
name='chocobo',
license="MIT",
description='chocobo is a python package for delicious chocobo recipes.',
version='v0.0.3',
long_description=README,
url='https://github.com/shaypal5/chocobo',
packages=setuptools.find_packages(),
python_requires=">=3.5",
install_requires=['requests'],
classifiers=[
# Trove classifiers
# (https://pypi.python.org/pypi?%3Aaction=list_classifiers)
'Development Status :: 4 - Beta',
'License :: OSI Approved :: MIT License',
'Programming Language :: Python',
'Programming Language :: Python :: 3.5',
'Programming Language :: Python :: 3.6',
'Topic :: Software Development :: Libraries',
'Topic :: Software Development :: Libraries :: Python Modules',
'Intended Audience :: Developers',
],
)複製代碼
首先,導入setuptools。這是一個很是有用代碼包,可輕鬆對Python包進行發行,即便它不包括在標準庫中(相似的distutils是比不了的),它仍然是當今Python包發行的標準,應該牢記於心。本文只使用了setuptools包中的兩個函數:setup和find_packagges。
在導入setuptools以後,調用setup()函數以前,只需將README.md 文件的內容讀入到全局變量 README中便可。
而後只需經過如下變量調用setuptools.setup() 函數便可:
· author:輸入姓名。
· author_email:輸入郵箱。
· name:代碼包的名稱,在本例中爲「chocobo」。
· license:在本例中爲字符串「MIT」,或選擇其餘許可證。
· description:代碼包的簡短介紹,控制在一行之內。例如:「chocobo代碼包是製做美味chocobo的食譜」
· version:表示封裝的當前版本的字符串。筆者在以後的文章中會介紹更簡潔的處理方法,可是目前,只須要在想要發佈新版本時手動增長一個數字就能夠了。一般的作法是將版本號前加入字母V,所以v1是第一個版本的版本字符串,但筆者建議將v0.0.1 視爲等效版本字符串並使用此格式。後文將詳細介紹這種作法的意義。
· long_description:表示README的內容。該部分是代碼包的詳細描述。也就是該頁面PyPI的內容(示例:https://pypi.org/project/pdpipe/)。
· url:可連接到代碼包的主頁。若是讀者沒有專用的站點,那麼存儲庫的URL是一個不錯的選擇。
· packages: 又一次提到了setuptools!根據命令,這個參數獲取要生成和發行/安裝的全部代碼包的名稱數組。從技術上講,能夠直接使用[「chocobo」]這個名字,可是最好是將其通用化,並使用setuptools 函數,它能處理更復雜的包和存儲庫結構。有兩個可選參數能夠做爲輸入數據,where 和exclude,但在這裏忽略不計。做爲結果,where可連接至安裝文件所在的目錄,包括全部子目錄,通常來講這樣已經足夠了。
· python_requires: 若是你的電腦支持Python的全部版本,就沒必要顧及此參數。若是不能,應該選擇一個適當的值。從技術上講,筆者不同意使用未經測試的版本,但保險期間目前咱們能夠進行適當的假設:
(1) 若是讀者正在使用Python2,特別是Python2.7版本,能夠得出如下兩點結論:(a)你獨樹一幟,十分優秀(b)你的電腦配置只需支持Python2.7便可,因此可使用「>=2.7」這個字符來編輯這個參數。另外,時代在進步,試試Python3吧。
(2) 若是讀者使用的是Python3,那麼任何Python版本都大於或等於用來開發代碼包的版本。以此類推,若是使用的是Python3.5,那麼應該設置成「>=3.5」。
· install_requires: 此處列出的是全部非標準庫代碼包的使用前提。例如,若是chocobo 須要requests和 pytz 才能運行的話,那麼該參數應設置爲:[「 requests」,「pytz」]。
· classifiers: 連同其餘成千上萬個代碼包一塊兒,你的代碼包也會很快PyPI上線。爲了進行區分,做者能夠向PyPI提供一個列表,列出trove分類器來對每一個版本進行分類,描述其用途、支持的系統和開發進度。而後,社區成員可使用這些標準化的分類器,根據本身的需求來查找項目(儘管不肯定誰會進行這項操做)。
這裏有全部可能用到的分類器:https://pypi.python.org/pypi?%3Aaction=list_classifiers
建議從如下幾個開始:
- 「Development Status :: 3 — Alpha」
- 「License :: OSI Approved :: MIT License」
- 「 Programming Language :: Python」
- 「 Programming Language :: Python :: 3.5」
- 「 Programming Language :: Python :: 3.6」
- 「 Programming Language :: Python :: 3.7」
- 「Topic :: Software Development :: Libraries」
- 「Topic :: Software Development :: Libraries :: Python Modules」
- 「Intended Audience :: Developers」
以上就是這一環節的所有內容。
步驟五:創建發行文件
Python包位於發行文件中,這些文件會統一被上傳到一個服務器中(一般是PyPI全局服務器),供公衆下載。
本文不會詳細介紹發行格式。筆者將使用標準方法(https://packaging.python.org/tutorials/packaging-projects/)構建兩個文件:源發行文件(基本上包含了代碼包)和wheel發行文件(wheel build distribution file)。
首先,確保安裝了最新版本的setuptools 以及 wheel:
python3 -m pip install --user --upgrade setuptools wheel
要構建發行文件,只需在setup.py所在的存儲庫的根目錄中運行如下命令:
python setup.py sdist bdist_wheel
在這一步,須要Python運行setup.py這個腳本,並向它發送兩個參數,生成源文件(參數sdist),以及wheel工具來構建發行文件(參數bdist_wheel)。
運行此命令時,將在調用目錄中建立三個文件夾: build, dist 和 chocobo.egg-info。對於.gitignore 文件來講,這三個能夠忽略不計。若是這些目錄已經存在(例如,該命令以前已經運行過了,最好用rm -rf build dist將這些目錄刪除掉,由於dist 下的任何有效代碼包文件都將被上傳。
要上傳的兩個文件位於dist 文件夾中:分別爲chocobo-0.0.3-py-none.any.whl (構建發行;是一個wheel 文件)和chocobo-0.0.3.tar.gz (源發行;是一個壓縮的tar 文件)。建立成功後,咱們繼續上傳的步驟!
步驟六:上傳
剩下的步驟就是將代碼包上傳到PyPI全局服務器!然而,用戶必須先在PyPI網站上註冊。按照註冊的步驟填寫用戶名和密碼。
若是想在上傳到PyPI全局服務器以前測試包,程序員也能夠在測試PyPI網站上註冊一個用戶。
如今,用於上傳的Python包將在.pypirc文本文件中查找PyPI用戶名和密碼(經過PyPI服務器進行驗證),該文件一般位於主文件夾中。建立後按以下所示進行填寫(testpypi 部分視具體狀況而定):
[distutils]
index-servers =
pypi
testpypi
[pypi]
username: teapot48
password: myPYPIpassword
[testpypi]
repository: https://test.pypi.org/legacy/
username: teapot48
password: MYtestPYPIpassword複製代碼
本文依照最新的方法將文件上傳到PyPI服務器中,並使用twine(上傳Python包的實用工具),而不是使用過期的python setup.py upload 。只需運行:
twine upload dist/*
若是想在PyPI服務器上進行測試,只需運行 twine upload — repository testpypi dist/*
不論如何,上傳.whl 文件時都應該能看到一個進度條,上傳.tar.gz 文檔時應該也能看到一個進度條,而後上傳就完成了。
如今能夠在PyPI官方網站上看到本身的Python包頁面了,你們也都能看到!
示例:https://pypi.org/project/birch/
大功告成!
留言 點贊 關注
咱們一塊兒分享AI學習與發展的乾貨
歡迎關注全平臺AI垂類自媒體 「讀芯術」
(添加小編微信:dxsxbb,加入讀者圈,一塊兒討論最新鮮的人工智能科技哦~)