我开始使用Python。我已将requirements.txt
和setup.py
添加到我的项目中。但是,我仍然对这两个文件的目的感到困惑。我已经读过setup.py
是为可再发行的东西而设计的,requirements.txt
是为不可再发行的东西而设计的。但我不确定这是否准确。
这两个文件真的打算如何使用?
答案 0 :(得分:39)
<强> requirements.txt 强>
这有助于您设置开发环境。像pip
这样的程序可以用来安装文件中列出的所有软件包。之后,您可以开始开发python脚本。如果您计划让其他人参与开发或使用虚拟环境,则特别有用。
这是你如何使用它:
pip install -r < requirements.txt
<强> setup.py 强>
这允许您创建可以重新分发的包。此脚本用于在最终用户的系统上安装程序包,而不是像pip install -r < requirements.txt
那样准备开发环境。
有关setup.py的详细信息,请参阅this answer。
项目的依赖关系列在两个文件中。
答案 1 :(得分:22)
简短的回答是requirements.txt
仅用于列出包裹要求。另一方面,setup.py
更像是一个安装脚本。除了包依赖关系之外,setup.py
还描述了应该打包(或编译,在本机模块的情况下(即用C语言编写))的文件和模块集,以及要添加到python的元数据包列表(例如包名,包版本,包描述,作者......)。
因为两个文件都列出了依赖关系,这可能会导致一些重复。请阅读下面的详细信息。
<强> requirements.txt 强>
此文件列出了python包要求。它是一个纯文本文件(可选择带注释),列出了python项目的包依赖项(每行一个)。它没有描述你的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 .
-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包。
答案 2 :(得分:4)
为了完整起见,这是我从3个不同角度看待它的方式。
这是official documentation(强调我的名字)中引述的精确描述:
尽管install_requires(在setup.py中)定义了单个项目的依赖项,而需求文件通常用于定义完整的Python环境的需求。>
尽管install_requires需求很小,但是需求文件通常包含详尽的固定版本列表,目的是实现可重复安装的完整环境。
但是可能仍然不容易理解,因此在下一节中,将提供2个事实示例来演示应该如何以不同方式使用这两种方法。
因此,它们的实际用法(应该是)不同
如果您的项目foo
将作为一个独立的库发布(这意味着其他人可能会import foo
),那么您(和您的下游用户)将希望拥有一个灵活的依赖关系声明,这样您的库就不会(也一定不能)对您的依赖关系的确切版本“挑剔”。因此,通常,您的setup.py将包含以下行:
install_requires=[
'A>=1,<2',
'B>=2'
]
如果您只是想以某种方式为应用程序bar
“精确记录”或“固定”您的EXACT当前环境,这意味着您或您的用户希望将您的应用程序bar
用作-is,即运行python bar.py
,您可能希望冻结环境,使其始终表现相同。在这种情况下,您的需求文件将如下所示:
A==1.2.3
B==2.3.4
# It could even contain some dependencies NOT strickly required by your library
pylint==3.4.5
实际上,我该使用哪一个?
如果您正在开发bar
将使用的应用程序python bar.py
,即使该应用程序只是“有趣的脚本”,仍建议您使用requirements.txt,因为,谁知道,下周(恰好是圣诞节)您会收到一台新电脑作为礼物,因此您需要在那儿重新设置确切的环境。
如果要开发foo
将使用的库import foo
,则必须准备setup.py。期。
但是您仍然可以选择同时提供require.txt,它可以:
(a)采用A==1.2.3
风格(如上文#2中所述);
(b)或仅包含一个神奇的.
.
大致等于“基于setup.py安装要求”,而无需重复。我个人认为这是最后一种方法,模糊了界限,增加了混乱,并没有真正增加价值,但这仍然是Python包装维护人员Donald在his blog post中提到的一种方法。