pyproject.toml 已取代 setup.py 成为现代 python 项目标准构建配置文件;它基于 pep 517/518,采用声明式 toml 格式,通过 [build-system] 和 [project] 分段定义构建后端与元数据,不执行代码,更安全、稳定、可审计。

pyproject.toml 正在取代 setup.py,成为现代 Python 项目标准的构建配置文件;setup.py 是旧方式,依赖运行 Python 代码来定义元数据和构建逻辑,而 pyproject.toml 是声明式、静态的 TOML 配置文件,更安全、可预测,也更利于工具链统一。
定位与作用不同
setup.py 原本是可执行脚本:它通过调用 setuptools.setup() 函数动态生成包信息,构建过程实际执行了 Python 代码。这意味着任何合法 Python 逻辑(比如读文件、条件判断、网络请求)都可能出现,带来安全隐患和缓存/复现难题。
pyproject.toml 是纯配置文件:按 PEP 517/518 标准定义,明确划分 [build-system](指定构建后端,如 setuptools、poetry-core、hatchling)和 [project](声明项目元数据,如 name、version、dependencies)。它不执行代码,只被构建工具解析,因此更稳定、可审计。
构建流程机制不同
使用 pyproject.toml 后,构建不再依赖 setup.py 脚本本身:
立即学习“Python免费学习笔记(深入)”;
- 构建工具(如 pip、build)先读取 pyproject.toml 中的
[build-system],知道该用哪个“构建后端”(backend) - 再调用该后端提供的 API(如
build_wheel())完成构建,整个过程与 setup.py 文件是否存在无关 - 如果项目仍保留 setup.py,且没有 pyproject.toml,pip 会回退到传统方式(直接运行 setup.py);但一旦存在 pyproject.toml,setup.py 默认被忽略(除非后端显式兼容)
实际项目中怎么选
新项目应直接使用 pyproject.toml:
- 用
[project]替代 setup.py 里的 setup() 参数(如requires-python = ">=3.8"、dependencies = ["requests>=2.25"]) - 用
[build-system]明确指定后端和最低版本(如requires = ["setuptools>=45", "wheel"]) - 若需额外功能(如动态 version、自定义命令),可搭配支持的后端(如 setuptools 支持
pyproject.toml+setup.cfg或setup.py的混合模式,但推荐尽量静态化)
老项目迁移时,可逐步将 setup.py 内容平移至 pyproject.toml,确认功能正常后删除 setup.py(注意检查 CI/CD 和发布流程是否适配)。
常见误区提醒
pyproject.toml 不等于“只能用 Poetry”或“必须放弃 setuptools”——它只是一个标准容器,后端可自由选择。setuptools 自 61.0 版起已原生支持 pyproject.toml 的 [project] 段;Poetry、Hatch、PDM 等工具也遵循同一规范,只是扩展了自己专属的配置段(如 [tool.poetry]),这些段对标准构建无影响。
另外,setup.py 并未被强制废弃,但官方(PyPA)已明确建议新项目不再创建 setup.py;Python 3.12+ 的 pip 默认启用 PEP 517 构建,进一步弱化 setup.py 的角色。










