本文 AI 產出,尚未審核

Python 課程 ── 封裝與發佈(Packaging & Distribution)

主題:Poetry 與 Flit


簡介

在 Python 生態系統中,封裝(Packaging)與發佈(Distribution)是把程式碼分享給其他開發者或部署到生產環境的關鍵步驟。傳統上,我們會使用 setup.pyrequirements.txt 等檔案,但隨著專案規模與依賴管理需求的提升,PoetryFlit 兩個工具因其簡潔、可預測的工作流程而受到廣大開發者的青睞。

  • Poetry:提供完整的依賴解析、虛擬環境管理與發佈功能,讓 pyproject.toml 成為唯一需要維護的設定檔。
  • Flit:主打「最小化」的封裝流程,適合單檔或小型套件,僅需要一個 pyproject.toml 即可完成打包與上傳。

本篇文章將帶你快速掌握兩者的核心概念、實作範例,以及在真實專案中如何選擇與避免常見陷阱。


核心概念

1. 為什麼使用 pyproject.toml

PEP 518 定義了 pyproject.toml 作為 建置系統 的統一入口。它取代了過去散落在 setup.pysetup.cfgMANIFEST.in 等檔案的設定,使得:

  • 工具獨立:同一個檔案可以被 Poetry、Flit、Black、isort 等工具共用。
  • 可重現環境:所有依賴(包括建置依賴)都寫在同一個地方,CI/CD 更加可靠。

重點:在使用 Poetry 或 Flit 前,先確定專案根目錄下已存在 pyproject.toml,且內容符合對應工具的規範。


2. Poetry 的工作流程

  1. 初始化專案poetry new my_pkg 會產生完整的目錄結構與 pyproject.toml
  2. 依賴管理poetry add requests 自動解析相容版本,並寫入 tool.poetry.dependencies
  3. 虛擬環境:Poetry 內建環境管理,poetry shell 直接切換到專屬的 venv。
  4. 打包與發佈poetry build 產生 .whl.tar.gzpoetry publish 直接推送至 PyPI。

範例:使用 Poetry 建立與發佈簡易套件

# 1. 建立新專案
poetry new hello_world
cd hello_world

# 2. 新增執行時依賴
poetry add click

# 3. 編寫程式碼 (src/hello_world/__init__.py)
#    這裡示範使用 click 建立 CLI
# src/hello_world/__init__.py
import click

@click.command()
@click.argument("name", default="World")
def main(name: str) -> None:
    """簡單的問候程式,輸入姓名即可得到問候語。"""
    click.echo(f"Hello, {name}!")
# pyproject.toml 片段
[tool.poetry.scripts]
hello = "hello_world:main"
# 4. 建置套件
poetry build

# 5. 發佈到測試 PyPI(先在 https://test.pypi.org 註冊帳號)
poetry config repositories.test-pypi https://test.pypi.org/legacy/
poetry publish -r test-pypi

完成後,任何使用者只要執行 pip install -i https://test.pypi.org/simple/ hello-world,即可在命令列呼叫 hello


3. Flit 的工作流程

Flit 的理念是「只要有 pyproject.toml,就能打包」。它不管理虛擬環境,也不提供依賴解析功能,適合:

  • 單檔或少量模組的套件。
  • 想要快速上傳至 PyPI,且不需要複雜的依賴約束。

範例:使用 Flit 打包與上傳

# 1. 安裝 Flit
pip install flit

# 2. 建立目錄與程式碼
mkdir myutils
touch myutils/__init__.py
# myutils/__init__.py
def add(a: int, b: int) -> int:
    """回傳兩個整數的加總。"""
    return a + b
# pyproject.toml(放在專案根目錄)
[build-system]
requires = ["flit_core >=3.2,<4"]
build-backend = "flit_core.buildapi"

[project]
name = "myutils"
version = "0.1.0"
description = "A tiny utility library for demonstration."
authors = [{name = "Your Name", email = "you@example.com"}]
requires-python = ">=3.8"
dependencies = []   # 若有外部依賴,直接列在此
# 3. 檢查與建置
flit build

# 4. 發佈到正式 PyPI(首次需要先設定 API token)
flit publish

注意:Flit 只會把 myutils 包含的 Python 檔案與 pyproject.toml 中宣告的資料一起打包;若需要額外的非程式碼檔案(如 README、LICENSE),必須在 project 區段的 readmelicense 欄位中說明。


4. 依賴與版本管理的差異

功能 Poetry Flit
依賴解析(解決衝突) ✅ 內建解決衝突與鎖檔 poetry.lock ❌ 需自行管理 requirements.txt 或手動指定
虛擬環境管理 ✅ 自動建立、切換 ❌ 不提供
多平台建置(wheel) ✅ 支援 poetry build ✅ 支援 flit build
發佈流程 ✅ 一鍵 publish ✅ 一鍵 publish
輕量化 中等(功能較多) 輕量(僅打包)

常見陷阱與最佳實踐

1. 依賴衝突未被偵測

  • Poetry:若直接編輯 pyproject.toml 而未使用 poetry add,Poetry 可能不會重新產生 poetry.lock,導致環境與鎖檔不一致。
    解法:每次手動修改依賴後執行 poetry lock --no-updatepoetry install

  • Flit:沒有鎖檔機制,若依賴版本寫成 requests>=2.0,不同環境安裝的實際版本可能不同。
    解法:在 dependencies 中使用固定版本或 ~=, ==,或額外維護 requirements.txt

2. 打包時遺漏檔案

  • 確保 include / exclude 設定正確。
  • 在 Poetry 中使用 packages = [{ include = "my_pkg", from = "src" }];在 Flit 中使用 module = "myutils"packages = ["myutils"]

3. 發佈到錯誤的 PyPI

  • Poetry 會保留多個 repository 設定,容易把測試套件推到正式 PyPI。
    最佳實踐:在 CI 中明確設定 --repository test-pypi;發佈前使用 poetry config pypi-token.pypi <TOKEN> 只授權正式 PyPI。

4. Python 版本相容性

  • pyproject.toml 中明確宣告 requires-python = ">=3.8,<4",避免使用者在不支援的 Python 版本安裝失敗。

5. 輸入錯誤的套件名稱

  • PyPI 套件名稱不可包含大寫、特殊符號。
  • Poetry/Flit 都會在 publish 前檢查名稱是否合法,但仍建議先在本地執行 poetry checkflit check

實際應用場景

場景 建議工具 為什麼
公司內部共享工具庫(多模組、需固定依賴) Poetry 鎖檔與虛擬環境保證所有開發者使用相同套件版本。
單檔 CLI 小工具(如 csv2json Flit 輕量、只需 pyproject.toml,快速上傳即可。
開源套件(希望提供 sdistwheel Poetry 或 Flit(視套件大小) 兩者皆支援 twine 兼容的檔案格式;Poetry 更適合有複雜依賴的情況。
CI/CD 自動化發佈 Poetry(配合 GitHub Actions) poetry publish --build 可在 CI 中一次完成建置與上傳。
需要自訂建置步驟(C 擴充套件) Poetry(可透過 build-system 加入 setuptools-rust Poetry 允許在 pyproject.toml 中混合多種建置後端。

總結

  • PoetryFlit 都是以 pyproject.toml 為核心的現代化封裝工具,選擇哪一個取決於專案的規模與需求。
  • Poetry 提供完整的依賴解析、虛擬環境與鎖檔管理,適合中大型套件或需要嚴格環境一致性的團隊。
  • Flit 則以「最小化」為目標,適合單檔或小型工具,快速完成打包與上傳。
  • 無論使用哪個工具,都應遵守 版本宣告、檔案包含、測試發佈 等最佳實踐,才能讓套件在 PyPI 上保持高品質與可維護性。

掌握了 Poetry 與 Flit 的使用方式,你就能把自己的程式碼從本機開發環境,順利、可靠地分享給全球的 Python 使用者。祝你封裝順利、發佈成功! 🚀