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.py、setup.cfg、requirements.txt、MANIFEST.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"
]