在 setuptools 项目的 pyproject.toml 中引用 requirements.txt
问题描述
当迁移基于 setuptools 的 Python 项目到现代 pyproject.toml
配置时,需要保留 pip-compile
工作流程的优点:
- ❗
requirements.txt
提供完整的依赖层级固定,确保 100% 可重复安装 - ❗ 透明显示依赖冲突,易于调试传递依赖关系
核心问题:
是否能在不依赖传统 setup.py
的情况下,直接在 pyproject.toml
中引用 requirements.txt
?
使用场景限制
此方案适用于非库项目(如应用程序),对于开源库建议采用宽松依赖声明
解决方案
✅ 推荐方案:使用 setuptools 的动态元数据(Dynamic Metadata)
要求 setuptools ≥ 62.6 版本
基础配置
在 pyproject.toml
中添加以下配置:
toml
[project]
name = "your-project"
version = "1.0.0"
dynamic = ["dependencies"]
[tool.setuptools.dynamic]
dependencies = { file = ["requirements.txt"] }
包含开发依赖
如需添加开发依赖(如 requirements-dev.txt
):
toml
[project]
dynamic = ["dependencies", "optional-dependencies"]
[tool.setuptools.dynamic]
dependencies = { file = ["requirements.txt"] }
optional-dependencies = {
dev = { file = ["requirements-dev.txt"] }
}
版本注意事项
txt
首次引入动态依赖文件支持
txt
自动将引用文件包含在 sdist 包中
重要限制
requirements.txt
每行必须符合 PEP 508 规范- 不支持 以下指令: ❌
-r / --requirement
❌-c / --constraint
❌-e / --editable
- 动态配置 optional-dependencies 时,必须全部动态声明
工作原理
通过 setuptools.dynamic
实现声明式依赖加载:
动态元数据注册
使用dynamic = ["dependencies"]
声明依赖将动态加载文件路径指定
tool.setuptools.dynamic.dependencies.file
定义目标文件路径构建阶段处理
setuptools 在构建包时自动读取文件内容并生成元数据
最佳实践
维护工作流示例
- 在
requirements.in
中声明基础依赖 - 通过
pip-compile
生成requirements.txt
:bashpip-compile requirements.in > requirements.txt
- 提交固定后的
requirements.txt
兼容性测试矩阵
setuptools 版本 | 支持特性 | 文件包含方式 |
---|---|---|
< 62.6 | ❌️ 不支持 | 不可用 |
62.6 - 66.0.x | ✅ 基本支持 | 需手动配置 MANIFEST.in |
≥ 66.1.0 | ✅ 完整支持 + 自动文件包含 | 完全自动 |
替代方案参考
- Hatch 构建系统(如需切换工具链):toml
[build-system] requires = ["hatchling", "hatch-requirements-txt"] [tool.hatch.metadata.hooks.requirements_txt] files = ["requirements.txt"]
- uv 工具链(依赖管理):bash
uv pip install -r requirements.txt
常见问题
如何检查文件合规性?
bash
# 示例检查(非官方工具)
grep -vE '^#|^$' requirements.txt | grep -Pv '^\s*\w+([=<>]=|;)\S+'
无输出则表示符合规范
安装前如何验证?
bash
# 测试构建过程
python -m build --no-isolation --sdist