pip 10.x.x升级后解析requirements文件的正确方式与最佳实践
嘿,这个问题我之前帮好几个开发者踩过坑,刚好给你唠清楚~
首先直接给你明确答案:绝对不要直接依赖pip._internal.req里的parse_requirements。原因很简单,_internal目录是pip官方明确标记为「内部专用」的区域,里面的API完全没有向后兼容性承诺——今天能用,下次pip更新可能就改结构甚至删掉了,到时候你的setup.py直接报错,得不偿失。
那不用parse_requirements的最佳实践有哪些呢?给你列几个最常用的方案:
方案1:手动读取requirements.txt(最推荐)
这是最简单也最稳妥的方式,完全不依赖pip的内部逻辑,兼容性拉满。代码示例如下:
from setuptools import setup def load_requirements(): # 读取requirements.txt,过滤掉注释和空行 with open('requirements.txt', 'r', encoding='utf-8') as req_file: return [ line.strip() for line in req_file if line.strip() and not line.startswith('#') ] setup( name="your-package-name", version="1.0.0", # 其他必要配置... install_requires=load_requirements(), )
这个方法能处理绝大多数场景,包括带版本号的依赖、注释行,甚至简单的环境标记(比如requests>=2.25.0; python_version >= "3.7"),setuptools本身会识别这些标记。
方案2:将依赖直接写在setup.py中
如果你的项目规模不大,或者不需要单独维护requirements.txt,可以直接把依赖列表写在setup.py的install_requires参数里,比如:
setup( # 其他配置... install_requires=[ "requests>=2.25.0", "numpy>=1.21.0", "pandas>=1.3.0" ] )
之后如果需要生成requirements.txt,只需要运行pip freeze > requirements.txt就能同步当前环境的依赖版本,方便其他开发者安装。
方案3:用第三方库处理复杂依赖(按需选择)
如果你的requirements.txt里有非常复杂的逻辑(比如嵌套的-r引用、复杂的环境条件),可以考虑用专门的依赖解析库,比如requirements-parser。不过要注意:因为setup.py运行时还没安装第三方库,所以你需要先在setup_requires里声明它,或者提前让用户安装。示例如下:
from setuptools import setup from requirements_parser import parse setup( setup_requires=["requirements-parser"], install_requires=[req.line for req in parse("requirements.txt").requirements], # 其他配置... )
不过这个方案不如手动读取通用,除非你真的有复杂需求,否则还是优先方案1。
总结一下:放弃依赖pip的内部parse_requirements,改用手动读取或者直接声明依赖,是长期维护项目的正确选择。
内容的提问来源于stack exchange,提问作者muthan

