Python应用依赖管理规范及pyproject.toml适配问题咨询
问题背景
我有一个Python应用(非库),希望发布为可通过pip安装的包。为确保该应用在当下、一个月后乃至两年后通过pip install都能稳定安装并运行,我计划使用pip-tools等工具固定所有依赖版本。
当前工作流
当前我的包涉及三个文件:
requirements.in:列出应用的直接依赖,无版本限制或采用宽松版本锁定,作为pip-compile的源文件。requirements.txt:由pip-compile从requirements.in生成的包含所有依赖(含传递依赖)的完整锁定文件,但该文件不属于Python wheel,因此pip install无法直接使用。setup.py:在install_requires中读取编译后的requirements.txt,以便将完整的固定依赖信息写入wheel元数据供pip install使用(示例如下):
# setup.py setup( ... # 伪代码 "install_requires": pip.parse(Path(".")/"requirements.txt") ... )
技术问询
- 该实现方式是否合理?是否存在更优方案?
- Python应用依赖管理的最佳实践是什么?是在
setup.py中固定所有依赖(含传递依赖),还是仅固定直接依赖(信任其自身的依赖锁定)? - 这种动态读取
requirements.txt的方式如何适配现代声明式的pyproject.toml方案?是否无法实现自动化,必须手动将编译后的requirements.txt内容复制到pyproject.toml的依赖部分?
回答
1. 当前实现的合理性与更优方案
当前方案有一定合理性,但存在潜在问题:
- 动态读取
requirements.txt会让setup.py的执行依赖pip和pathlib,打包环境缺失这些工具时会直接报错; pip.parse的输出格式不一定完全符合PEP 508规范,可能触发wheel元数据校验失败。
更优方案:
- 用
pip-compile直接生成符合PEP 508的依赖列表,写入临时文件或直接生成setup.py/pyproject.toml的依赖段; - 或者编写简单脚本,将
requirements.txt的内容转换为合规格式后,同步到打包配置文件中,避免动态读取的依赖风险。
2. Python应用依赖管理的最佳实践
对于非库类的Python应用,最佳实践是固定所有依赖(包括传递依赖)的精确版本:
- 应用需要长期稳定运行,传递依赖的版本更新可能引入兼容性问题(比如小版本更新改变核心API);
- 仅固定直接依赖的话,其依赖的包后续可能出现破坏性变更,导致应用运行失败;
- 注意:必须使用精确版本号(如
requests==2.31.0)而非版本范围,确保每次安装的依赖完全一致。
(注:库类项目则相反,应仅固定直接依赖的版本范围,给下游用户留足依赖适配空间,但你的场景是应用,全量锁定更合适)
3. 适配pyproject.toml的方案
不需要手动复制,完全可以通过自动化脚本实现同步:
- 编写Python脚本,读取
requirements.txt内容,过滤注释和空行,将每一行转换为PEP 508格式(带哈希的行可以去掉哈希,因为wheel元数据不支持哈希校验); - 用
tomllib(Python 3.11+内置)或tomli-w(低版本兼容)读写pyproject.toml,将转换后的依赖列表写入project.dependencies字段; - 将脚本加入打包前的流程(比如
pip-compile之后执行),确保pyproject.toml的依赖始终与requirements.txt同步。
简单脚本示例:
import tomllib import tomli_w # 读取并处理requirements.txt with open("requirements.txt", "r") as f: dependencies = [ line.strip() for line in f if line.strip() and not line.startswith("#") ] # 读取pyproject.toml并更新依赖 with open("pyproject.toml", "rb") as f: pyproject_data = tomllib.load(f) pyproject_data["project"]["dependencies"] = dependencies # 写回pyproject.toml with open("pyproject.toml", "wb") as f: tomli_w.dump(pyproject_data, f)
内容的提问来源于stack exchange,提问作者timmwagener
相关产品推荐
相关产品推荐

