Home 製作 Python 第三方套件
Post
Cancel

製作 Python 第三方套件

前情提要

前陣子在滑 GitHub 的時候看到有朋友寫了個 python 的套件,所以就覺得自己也可以來試試看,於是就花了一些時間寫出了 RandomUsers 這個套件。

自己其實覺得這個套件沒有太大用途,但既然剛好有個機會嘗試新事物,何樂而不為。所以這篇文章就是一些經驗,給別人看的同時也留給自己當筆記。

Setup

首先,我們要安裝一些必要的套件,使用我們的好朋友 pip 來幫忙。

第一個 twine 是最後上傳到 PyPI 會用到的工具,而第二個 setuptools 則是隨後要寫 setup.py 會用到的套件,會讓寫 setup.py 的過程輕鬆很多。

setup.py

首先我們必須先寫出 setup.py,它裡面包含了整個套件所需的資訊。以下是一個簡單的範例。

雖然有很多欄位,但其實都不是必需的,只是 build 完會變出一些 UNKNOWEN 之類的名字,所以正常來說還是要填。

基本上 nameversionpackages 是比較重要的欄位,其他的欄位就比較可選擇不填,下面我們分項說明。

  • name 是指這個 package 的名字,也就是別人要安裝套件時要打的。
  • version 顧名思義就是版本,可以參考 PEP 440 – Version Identification and Dependency Specification 的規則,這邊我直接使用 x.x 來命名。
  • packages 是這個套件裡面要包含的 package,在上面的範例我用 setuptools 提供的 find_packages 來自動尋找,也可以加上 exclude 的選項來去掉不該被包進去的 package,像是 testsdocs 等等,也可以直接指定,像是使用 packages=["mypackage"]
  • description 是對於這個套件的簡短描述,會在 PyPI 看到他。而 long_description 會出現在 PyPI 網站的 Project description 部分,我直接拿會顯示在 GitHub 的 README.md 來用。也因為是直接拿它來用,所以要記得設定 long_description_content_type,不然他會以純文字顯示。
  • authorauthor_email 是自己本人的資訊,url 是這個專案的網址,我選擇放 GitHub repo,畢竟也沒有其他可放,也因為放 GitHub repo,所以 PyPI 有顯示 GitHub statistics。license 可以選擇自己喜歡的。上述幾項都會在 PyPI 的網站看到。
  • install_requires 包括了這個套件所需的其他第三方套件,如 requestsnumpy 等等。如果要指定版本的話要使用 extras_require,使用可以參考 GitHub pyTelegramBotAPI/setup.py。如果對 python 版本有需求的話,可以使用 python_requires
  • classifiers 是一些資訊,官方稱之為 “A list of strings describing the categories for the package”,也會顯示在 PyPI 的頁面上。我自己在上面放了一些 python 的版本資訊。

如果需要更詳細的說明或更多欄位的用途,可以參考官方 Keywords。而這些資料除了可以直接寫在 setup.py,也可以寫在 setup.cfg,但我這邊就不提這個方式,有需要的話可以參考 setuptools: Quickstart 的轉換。

寫套件

結束 setup.py 之後,我們可以開始寫套件了。

我們要先建立一個跟套件名稱同名的目錄,在這裡我們使用 mypackage 來舉例。接下來要在裡面建立 __init__.py,這表示他是一個 package。然後就可以開始寫套件內容,但要注意的是,在建立一些 class 或是 function 之後,需要把他們全部 import 進 __init__.py

在寫完後,我們就可以開始使用這個套件了,可以試試 pip install .,理論上應該會跑出一大串訊息然後告訴你成功安裝了套件 mypackage。這時候打開 python interpreter,嘗試 import mypackage,應該就可以看到他順利引入,而你也可以開始使用你自己的套件。

上傳至 PyPI

自己用過之後,就可以發佈到 PyPI 給全世界的人下載,這時候就需要用到一開始安裝的 twine 了。

但在上傳之前,我們必須要先有一個套件的壓縮檔,所以我們需要讓 python 幫我們處理一下。

在上傳之前,我們還必須有一個 PyPI 的帳號,可以用 twine 來建立,但我選擇用網站的方式。基本上沒有什麼特別的,但 Username 建議要跟 setup.py 裡面的 author 一樣,不然可能之後會出事。註冊完後,就來到最後一步。

下完這個指令後,他會要求你登入,接著就會開始上傳。結束之後就可以回到剛剛註冊的頁面,理論上就可以看到套件已經妥當的在 PyPI 給大家下載了。

之後如果需要更新套件的話,就只要再重複一次上面三個指令即可,但可能會遇到 HTTPError: 400 Client Error: File already exists.,這是因為 PyPI 不允許重複使用檔名,所以這種狀況通常是因為忘了改版本號。如果改過還是不行的話可以試試先把 dist 刪除再重新下指令。

而 PyPI 也有提供一些 badge 可以嵌在 README 裡面,這邊是一些常見的例子,可以多多利用讓 README 看起來不單調。

使用 GitHub Actions 自動化

前面我們手動把套件上傳到 PyPI,在這章我們把這個步驟交給 GitHub Actions 來完成。我們需要先到 repo 底下的 Actions 頁面,應該會看到如下圖的介面。

選擇第一個 Publish Python Package,然後應該就會進到編輯設定檔的頁面,檔名不限,它會自動掃。基本上這時候那個設定檔就會指示 GitHub Actions 把套件上傳到 PyPI 了,但我們可以做一點微幅的更動。但在開始之前,我們必須先來看看他的 components。

  • workflow 是 precedure,基本上現在在編輯的設定檔就是一個 workflow。
  • job 是大步驟的概念,由許多 step 組成,如果要做相依性 (如先經過測試才能 deploy 之類的)要在這層處理,不然會自動平行執行。
  • step 是步驟,由 job 依序執行。
  • action 在 GitHub Actions 是最小的單位,一個 step 可以包含數個 action

另外,在最上面還有 nameon,前者的用途是命名這個 workflow,而後者是指定在甚麼時候觸發他,我選擇在每次 push 的時候都觸發,這樣每次 push 他就會幫我自動更新 PyPI 上的套件。更改完後應該會類似 RandomUsers GitHub Actions

最後還需要在 repo 的設定裡面的 secrets 裡面加入 PYPI_API_TOKEN,這樣 GitHub Actions 才能通過身分認證。而這個 API token 可以在 PyPI 的 Account Setting 生成。

做完以上後,就可以把下一個新版本 push 到 GitHub,然後看看是否有成功觸發 GitHub Actions 並更新到 PyPI,有可能會遇到一些語法錯誤,畢竟每個 CI/CD 工具的設定檔都有自己的語法。

References

This post is licensed under CC BY 4.0 by the author.