简短的回答是requirements.txt 仅用于列出包要求。另一方面,setup.py 更像是一个安装脚本。如果你不打算安装 python 代码,通常你只需要requirements.txt。
文件setup.py 描述了除了包依赖之外,应该打包(或编译,在本机模块的情况下(即,用C 编写)的情况下)的文件和模块集,以及要添加的元数据到 python 包列表(例如包名称、包版本、包描述、作者……)。
因为这两个文件都列出了依赖关系,这可能会导致一些重复。阅读下文了解详情。
requirements.txt
此文件列出了 python 包的要求。它是一个纯文本文件(可选地带有 cmets),列出了你的 python 项目的包 dependencies(每行一个)。它没有描述你的 python 包的安装方式。您通常会使用 pip install -r requirements.txt 来使用需求文件。
文本文件的文件名是任意的,但通常是requirements.txt。在探索其他 python 包的源代码存储库时,您可能会偶然发现其他名称,例如 dev-dependencies.txt 或 dependencies-dev.txt。它们的目的与dependencies.txt 相同,但通常列出特定包的开发人员感兴趣的其他依赖项,即在发布前测试源代码(例如 pytest、pylint 等)。包的用户通常不需要整套开发人员依赖项来运行包。
如果存在多个requirements-X.txt 变体,那么通常其中一个会列出运行时依赖项,而另一个会列出构建时或测试依赖项。一些项目还级联他们的需求文件,即当一个需求文件包含另一个文件时(example)。这样做可以减少重复。
setup.py
这是一个 Python 脚本,它使用 setuptools 模块来定义一个 Python 包(名称、包含的文件、包元数据和安装)。与requirements.txt 一样,它也会列出包的运行时依赖项。 Setuptools 是构建和安装 python 包的事实上的方式,但它有它的缺点,随着时间的推移,它催生了新的“元包管理器”的开发,比如 pip。 setuptools 的示例缺点是它无法安装同一软件包的多个版本,并且缺少卸载命令。
当 python 用户执行pip install ./pkgdir_my_module(或pip install my-module)时,pip 将在给定目录(或模块)中运行setup.py。同样,任何具有setup.py 的模块都可以安装pip,例如通过在同一文件夹中运行 pip install .。
我真的需要两者吗?
简短的回答是否定的,但两者兼得很好。它们实现不同的目的,但它们都可以用来列出你的依赖关系。
您可以考虑一个技巧来避免在requirements.txt 和setup.py 之间重复您的依赖关系列表。如果您已经为您的包编写了一个完全可用的setup.py,并且您的依赖项大多是外部的,您可以考虑使用一个简单的requirements.txt,仅包含以下内容:
# requirements.txt
#
# installs dependencies from ./setup.py, and the package itself,
# in editable mode
-e .
# (the -e above is optional). you could also just install the package
# normally with just the line below (after uncommenting)
# .
-e 是一个特殊的pip install 选项,它以可编辑 模式安装给定的包。当pip -r requirements.txt 在这个文件上运行时,pip 将通过./setup.py 中的列表安装你的依赖项。可编辑选项将在您的安装目录中放置一个符号链接(而不是鸡蛋或存档副本)。它允许开发人员从存储库中编辑代码,而无需重新安装。
当您的软件包存储库中同时拥有这两个文件时,您还可以利用所谓的“setuptools extras”。您可以在 setup.py 中的自定义类别下定义可选包,并使用 pip 从该类别中安装这些包:
# setup.py
from setuptools import setup
setup(
name="FOO"
...
extras_require = {
'dev': ['pylint'],
'build': ['requests']
}
...
)
然后,在需求文件中:
# install packages in the [build] category, from setup.py
# (path/to/mypkg is the directory where setup.py is)
-e path/to/mypkg[build]
这会将所有依赖项列表保留在 setup.py 中。
注意:您通常会在沙箱中执行 pip 和 setup.py,例如使用程序 virtualenv 创建的沙箱。这将避免在项目开发环境的上下文之外安装 python 包。