pyproject.toml 项目管理完全指南
pyproject.toml 是现代 Python 项目的标准配置中心:构建系统、项目元数据、依赖声明、工具配置与动态版本。本文系统讲解各核心区块的用法。
直接回答:pyproject.toml 是 Python 项目的"宪法":PEP 518 引入、PEP 621 标准化,统一了构建配置、项目元数据与依赖声明,还把各工具(Ruff/Mypy/Pytest)的配置收拢一处——Poetry、PDM、Hatch、uv 都以它为中心。
为什么它取代了 setup.py
老时代的 setup.py 是可执行代码——想读个版本号都得先跑起来,安全隐患与复杂度齐飞;setup.cfg 静态但表达力弱。pyproject.toml 是纯声明式 TOML:静态可读、机器友好、标准统一,工具链各司其职而不互相发明格式。
核心区块解剖
[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"
[project]
name = "my-awesome-lib"
version = "1.2.0"
description = "让某事更简单的库"
readme = "README.md"
requires-python = ">=3.10"
license = "MIT" # 需支持 PEP 639 的构建后端
authors = [{ name = "张三", email = "zs@example.com" }]
dependencies = [
"requests>=2.31",
"pydantic>=2.0",
]
[project.optional-dependencies]
dev = ["pytest>=8", "ruff"]
docs = ["sphinx"]
[project.urls]
Homepage = "https://example.com"
Issues = "https://example.com/issues"
三个区块分工:[build-system] 告诉 pip 用什么构建你;[project] 是 PEP 621 标准元数据(任何工具都能读);[project.optional-dependencies] 定义可选依赖组(pip install pkg[dev])。
命令行入口
[project.scripts]
mycli = "mylib.cli:main"
安装后 mycli 命令直接可用——Python 包分发命令行工具的标准姿势。
工具配置收拢处
[tool.ruff]
line-length = 120
[tool.mypy]
strict = true
[tool.pytest.ini_options]
testpaths = ["tests"]
[tool.coverage.run]
source = ["src"]
[tool.*] 命名空间是各工具的认领区——项目根目录从此不再散落十几个 rc 文件。
动态版本
版本号不想写两处?让构建后端从代码里读:
[project]
# 合并到原 project 表,并删除原 version 字段;不要重复声明同名表
name = "my-awesome-lib"
dynamic = ["version"]
[tool.hatch.version]
path = "src/mylib/__about__.py" # 文件里有 __version__ = "1.2.0"
或从 Git 标签派生(hatch-vcs / setuptools-scm):配置相应插件和构建后,Git 标签可作为版本来源;打标签本身不会发布包,彻底消灭"忘了改版本号"。
依赖声明的分寸
库与应用不同:库的依赖约束要宽(>=2.0,给用户留兼容空间),精确锁定交给应用的 lock 文件;应用可以更严,且应配 lock(uv.lock/pdm.lock/poetry.lock)保证部署可复现。
常见问题(FAQ)
Q:pyproject.toml 能完全替代 requirements.txt 吗?
A:定位不同:pyproject 是依赖声明(范围约束),requirements 可写版本范围或 pin,锁文件记录解析结果。应用部署仍需 lock 文件;requirements.txt 可以作为由 pyproject 导出的产物存在。
Q:构建后端选哪个?
A:Hatchling(Hatch 后端,简洁现代)、setuptools(老牌全能)、pdm-backend、flit-core(纯库极简)都合规。新项目推荐 hatchling。
Q:src 布局还要吗?
A:要。src/mypkg/ 布局防止"在项目根目录碰巧 import 成功、发布后却缺文件"的经典事故,并按构建后端配置包发现;不存在跨后端统一的 packages 键。
官方参考
本文基于官方文档整理,未进行运行时或性能测试。示例中的业务函数、数据模型和部署地址需结合项目补全;局部片段不等同于完整生产应用。