Python pyproject.toml 設定檔

pyproject.toml 是 Python 專案的標準設定檔,用來定義專案的建置系統依賴、專案元數據以及各種工具的設定。它的出現解決了過去 Python 專案依賴多個設定檔(setup.py, requirements.txt, setup.cfg, MANIFEST.in, 各種 linter 設定檔)混亂的局面。

為什麼需要 pyproject.toml?

過去,Python 專案通常使用 setup.py 來定義專案資訊。但 setup.py 是一個 Python 腳本,執行它可能存在安全風險,且難以靜態分析。

pyproject.toml (PEP 518) 引入了解決以下問題:

  1. 明確的建置依賴:在安裝專案之前,需要先安裝哪些工具(如 setuptools, wheel, poetry-core)。
  2. 統一的設定格式:TOML 格式易於閱讀和寫入,且許多工具(Black, Isort, Pytest, MyPy)都支援從中讀取設定。
  3. 標準化的專案元數據:PEP 621 定義了 [project] 表格,統一了專案名稱、版本、依賴的定義方式。

檔案結構

一個標準的 pyproject.toml 通常包含以下幾個部分:

1. 建置系統 [build-system]

告訴 pip 或其他安裝工具,這個專案需要什麼工具來建置。

[build-system]
requires = ["setuptools>=61.0", "wheel"]
build-backend = "setuptools.build_meta"

如果是使用 Poetry:

[build-system]
requires = ["poetry-core>=1.0.0"]
build-backend = "poetry.core.masonry.api"

2. 專案資訊 [project] (PEP 621)

定義專案的名稱、版本、描述、作者、依賴等。

[project]
name = "my-awesome-project"
version = "1.0.0"
description = "A short description of my project"
readme = "README.md"
requires-python = ">=3.8"
license = {file = "LICENSE"}
authors = [
  {name = "User Name", email = "user@example.com"},
]
dependencies = [
  "requests>=2.28.0",
  "fastapi>=0.95.0",
]

[project.optional-dependencies]
dev = [
  "pytest",
  "black",
]
test = [
  "pytest",
  "coverage",
]

關鍵屬性詳解

dependencies (必要依賴)

dependencies 是一個字串列表,列出了專案執行時必須安裝的套件。這相當於過去的 requirements.txt 內容。

  • 格式遵循 PEP 508 標準。
  • 可以指定版本範圍,如 requests>=2.0

project.optional-dependencies (可選依賴)

這是一個表格 (Table),用來定義「額外」的依賴群組。這些依賴不是執行主程式所必需的,但在特定情境下(如開發、測試、產生文件)很有用。

常見的群組名稱包括:

  • dev:開發工具(如 linter, formatter)。
  • test:測試框架(如 pytest)。
  • docs:文件生成工具(如 Sphinx)。

如何安裝可選依賴?

當使用者想要安裝這些額外依賴時,可以在套件名稱後面加上中括號 []

# 安裝專案本身 + dev 群組的依賴
pip install .[dev]

# 同時安裝 dev 和 test 群組
pip install .[dev,test]

# 如果是從 PyPI 安裝
pip install my-package[dev]

3. 工具設定 [tool.tool_name]

許多開發工具支援將設定寫在 pyproject.toml 中,避免專案根目錄充斥著各種 rc 檔案。

Black (格式化工具):

[tool.black]
line-length = 88
target-version = ['py38']

Isort (Import 排序):

[tool.isort]
profile = "black"

Pytest (測試框架):

[tool.pytest.ini_options]
minversion = "6.0"
addopts = "-ra -q"
testpaths = [
    "tests",
]

常見範例

使用 Setuptools (傳統方式現代化)

如果你習慣使用 setuptools,現在可以直接用 pyproject.toml 取代 setup.py

[build-system]
requires = ["setuptools>=61.0"]
build-backend = "setuptools.build_meta"

[project]
name = "example-pkg"
version = "0.0.1"
authors = [
  { name="Example Author", email="author@example.com" },
]
description = "A small example package"
readme = "README.md"
requires-python = ">=3.7"
classifiers = [
    "Programming Language :: Python :: 3",
    "License :: OSI Approved :: MIT License",
    "Operating System :: OS Independent",
]

[project.urls]
"Homepage" = "https://github.com/pypa/sampleproject"
"Bug Tracker" = "https://github.com/pypa/sampleproject/issues"

使用 Poetry

Poetry 使用自己的 [tool.poetry] 區塊來管理依賴,這與 PEP 621 [project] 略有不同(Poetry 正在計畫支援 PEP 621)。

[tool.poetry]
name = "my-project"
version = "0.1.0"
description = ""
authors = ["Your Name <you@example.com>"]

[tool.poetry.dependencies]
python = "^3.9"
requests = "^2.28.0"

[build-system]
requires = ["poetry-core>=1.0.0"]
build-backend = "poetry.core.masonry.api"

總結

pyproject.toml 是現代 Python 開發的核心。它讓專案結構更乾淨、設定更統一。無論你是使用 setuptools、flit、poetry 還是 uv,都應該使用 pyproject.toml 來管理你的專案。