跳至主要内容

Python - pyproject.toml

pyproject.toml 是一個「統一管理 Python 專案設定與依賴」的標準檔案,硬要比喻的話可以想成「Python 專案的 package.json (JS)」。

結構

pyproject.toml 主要用來描述:

  • 專案的基本資訊 (名稱、版本、作者等 metadata)
  • 專案的依賴 (需要哪些套件、版本範圍)
  • 專案要用什麼 build system (如 setuptools、poetry-core、hatchling、......)
  • 各種工具的設定 (如 black、isort、ruff、pytest、......)

它的出現是因為 PEP 518 (定義 build-system)、PEP 517 (建置後端介面)、PEP 621 (專案 metadata) 等標準,讓 Python 專案有一個「單一、標準化」的設定入口,逐步取代過去散落的 setup.pysetup.cfgrequirements.txtMANIFEST.in 等等的設定檔。

🌰 來個例子說明 🌰
這段 pyproject.toml 可以理解成「用 setuptools 打包的 Python 專案,額外定義了一組名為 test 的測試用依賴,以及 pytest 的設定」。

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

[project]
name = "coding-test"
version = "0.1.0"
description = "SDET interview BDD demo with pytest-bdd"
requires-python = ">=3.11"
dependencies = [
"fastapi>=0.110",
"pydantic>=2.0"
]

[project.optional-dependencies]
test = [
"pytest==9.0.2",
"pytest-bdd==7.2.0",
"requests==2.32.5",
"selenium==4.40.0",
"webdriver-manager==4.0.2",
"flask==3.1.0"
]

[tool.pytest.ini_options]
addopts = "-q"
testpaths = ["tests"]
markers = [
"unit: Unit tests that test the AuthService directly (no web server needed)",
"api: API tests that test HTTP endpoints (requires web server running)",
"ui: UI tests that require a web server running on localhost:3000"
]

[build-system]

現在我們一個一個來看
首先是 [build-system],它的作用是告訴別人怎麼 build 這個專案

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

意思就是

  • 這個專案用 setuptools 來打包,並且至少是 68 以上版本 (其實 wheel 非必要,但相容舊版)
  • 使用 setuptools.build_meta 當作 build backend

[project]

再來是 [project],他有點像是專案的身分證

name = "coding-test"
version = "0.1.0"
description = "SDET interview BDD demo with pytest-bdd"
requires-python = ">=3.11"
dependencies = [
"fastapi>=0.110",
"pydantic>=2.0"
]

意思就是

  • 專案名稱叫做 "coding-test" (之後打包成套件也會叫這個名字)
  • 版本號 "0.1.0"
  • 這個專案的簡述是 "SDET interview BDD demo with pytest-bdd"
  • 支援的 Python 版本至少是 3.11 以上
  • dependencies 指的是正式環境依賴,這些在安裝專案時會一起安裝 而這些資訊會被寫入套件的 metadata。

[project.optional-dependencies]

這邊的 [project.optional-dependencies] 是開發或測試依賴,跟 dependencies 不一樣的是,他可以依使用狀況決定要不要裝

[project.optional-dependencies]
test = [
"pytest==9.0.2",
"pytest-bdd==7.2.0",
"requests==2.32.5",
"selenium==4.40.0",
"webdriver-manager==4.0.2",
"flask==3.1.0"
]

安裝方式也很簡單

pip install .[test]

[tool.xxx]

看到 [tool.xxx] 基本上就是工具集中管理,像下面這段 [tool.pytest.ini_options] 就是為了整合原本的 pytest.ini

[tool.pytest.ini_options]
addopts = "-q"
testpaths = ["tests"]
markers = [
"unit: Unit tests that test the AuthService directly (no web server needed)",
"api: API tests that test HTTP endpoints (requires web server running)",
"ui: UI tests that require a web server running on localhost:3000"
]

Reference