何时使用pip requirements文件而不是在setup.py中使用install_requires?

111
我正在使用pip和virtualenv来打包和安装一些Python库。我想这是一个相当常见的场景。我是几个库的维护者,可以明确指定它们的依赖关系。我的一些库依赖于第三方库,而这些第三方库具有我无法控制的传递依赖关系。
我的目标是让pip在安装我的库时下载/安装所有上游依赖项。我在pip文档中遇到了困难,不知道 requirements files 是否能够自行完成此操作,或者它们是否真的只是使用install_requires 的补充。
我是否应该在所有库中都使用install_requires 来指定依赖关系和版本范围,然后仅在生产构建时使用requirements文件来解决冲突和/或冻结它们?
假设我生活在一个想象的世界(我知道,我知道),我的上游依赖关系很简单,并且保证永远不会发生冲突或破坏向后兼容性。我是否需要使用pip要求文件,还是只需让pip / setuptools / distribute 根据install_requires来安装所有内容?
这里有很多类似的问题,但我找不到与何时使用其中之一或如何和谐地同时使用它们的基本问题相同的问题。

3
这篇文章非常好地解释了"setup"和"requirement"之间的关系,以及它们如何相互融合。 - Björn Pollex
相关链接:https://dev59.com/w2Yq5IYBdhLWcg3wixJr - Ciro Santilli OurBigBook.com
4个回答

74

我的理念是install_requires应该指示你所需的最低限度。如果你知道某些版本不可用,则可能包括版本要求;但是,如果您不确定(例如,您不确定依赖项的未来版本是否会破坏您的库),则不应具有版本要求。

另一方面,要求文件应指示您知道可以使用的内容,并且可能包括您建议的可选依赖项。例如,你可能使用SQLAlchemy,但建议使用MySQL,在要求文件中加入MySQLdb)。

因此,总之:install_requires是为了避免让人们接触到你知道不可行的事情,而要求文件则是为了引导人们接触到你知道可行的事情。其中一个原因是,install_requires要求始终被检查,而且不能在不实际更改包元数据的情况下禁用。因此,您无法轻松尝试新组合。要求文件仅在安装时检查。


6
这是否意味着你应该在requirements.txt中镜像setup.pyinstall_requires=依赖项? - proppy
16
在setup.py和requirements文件中都有依赖项是很危险的,因为这种重复会导致两者不同步。 - Sebastian Blask
1
还有,你们实际上是如何使用它的呢?我猜想,你们会先使用 requirements 文件来确保程序能够正常运行。然后再通过 pip 安装实际的软件包。你们永远不可能使用 -U 选项,因为那样可能会覆盖掉 requirements 文件中指定的依赖关系。那么你们该如何进行升级呢? - Sebastian Blask
1
这个答案是否同样适用于应用程序和软件包?想象一下,我的网络应用程序(一个应用程序)依赖于某些工具(一个软件包),它们都依赖于requests软件包。如果some-tool有一个requirements.txt文件,固定了requests的特定版本或版本范围,那么这似乎会为my-web-app创建潜在问题,因为它可能指定了冲突的版本/版本范围。 - Reece
2
应该只有一种安装软件包的方式。因此,除非您想让其他贡献者感到困惑,否则不建议同时存在两种安装方式。 - Gewthen
这个回答有点令人困惑。为什么我要在requirements.txt文件中添加不必要的包呢? - async

27

这是我在setup.py中放置的内容:

# this grabs the requirements from requirements.txt
REQUIREMENTS = [i.strip() for i in open("requirements.txt").readlines()]

setup(
    .....
    install_requires=REQUIREMENTS
)

26
小心,要求文件可能包含注释和包含的内容。您应该使用pip解析器。 - Romain Hardouin
1
是的,最终我改变了这个方法以去除注释。pip解析器看起来比我的答案更好。 - rbp
7
如果requirements.txt文件中只包含在setup.py中已经存在的内容,为什么还要使用requirements.txt文件? - Sebastian Blask
2
@RomainHardouin,正如在您链接的答案评论中提到的那样,pip 不应该被用来那种方式。 - akaihola
1
是的,这对我起作用,直到需要在要求中使用关键的 --extra-index-url,然后这个问题就爆发了。感谢 @RomainHardouin - Tommy
显示剩余2条评论

20

Python打包用户指南有一篇关于此主题的页面,我强烈建议你阅读:

简述:

install_requires 用于列出必须安装以使软件包正常工作的依赖项。它不是用来固定依赖项到特定版本的,但是可以接受区间范围的写法,例如 install_requires=['django>=1.8']install_requirespip install name-on-pypi 和其他工具所使用。

requirements.txt 只是一个文本文件,你可以选择运行 pip install -r requirements.txt 安装其中所有的依赖及其子依赖项。它的目的是将所有依赖项和子依赖项的版本固定下来,像这样:django==1.8.1。你可以使用 pip freeze > requirements.txt 创建一个该文件。(有些服务,如Heroku,会自动运行 pip install -r requirements.txt)。pip install name-on-pypi 只查看 install_requires,而不查看 requirements.txt


7
我只使用 setup.pyinstall_requires,因为这样只需要查看一个地方。它的功能与使用要求文件一样强大,而且没有需要维护的重复内容。

问题在于何时使用其中一个,我没有明确说明,但我的答案是我总是使用其中一个而不是另一个。这不就是回答问题的方式吗? - Sebastian Blask

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接