我开始使用Python。我已经添加了requirements.txt
和setup.py
我的项目。但是,我仍然对两个文件的目的感到困惑。我读过,它setup.py
是为可再发行的事物而requirements.txt
设计的,并且是为不可再发行的事物而设计的。但是我不确定这是正确的。
如何真正使用这两个文件?
我开始使用Python。我已经添加了requirements.txt
和setup.py
我的项目。但是,我仍然对两个文件的目的感到困惑。我读过,它setup.py
是为可再发行的事物而requirements.txt
设计的,并且是为不可再发行的事物而设计的。但是我不确定这是正确的。
如何真正使用这两个文件?
Answers:
requirements.txt
这可以帮助您设置开发环境。诸如此类的程序pip
可用于一次安装文件中列出的所有软件包。之后,您可以开始开发python脚本。如果您计划让其他人参与开发或使用虚拟环境,则特别有用。这是您的用法:
pip install -r requirements.txt
setup.py
这使您可以创建可以重新分发的软件包。该脚本旨在将软件包安装在最终用户的系统上,而不是像在准备开发环境那样pip install -r requirements.txt
。有关setup.py的更多详细信息,请参见此答案。
两个文件中都列出了项目的依赖项。
简短的答案是requirements.txt
仅列出软件包要求。setup.py
另一方面更像是一个安装脚本。如果您不打算安装python代码,通常只需要requirements.txt
。
该文件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
存在多个变体,则通常一个将列出运行时依赖性,而另一个将列出运行时依赖性或测试依赖性。一些项目还会层叠其需求文件,即一个需求文件包含另一个文件时(例如)。这样做可以减少重复。
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
。可编辑选项将在您的安装目录中放置一个符号链接(而不是egg或存档副本)。它允许开发人员从存储库中就地编辑代码,而无需重新安装。
当两个文件都位于软件包存储库中时,您还可以利用所谓的“ 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,例如使用program创建的virtualenv
。这样可以避免在项目开发环境的上下文之外安装python软件包。
.
W / O -e
内requirements.txt
。此方法仅将所有需求委托给setup.py
您,而无需强迫任何人进入可编辑模式。用户仍然可以这样做pip install -e .
。
-e .
还会使用setup.py查找依赖项,但是将当前文件夹(使用符号链接)链接到pip安装文件夹中,而不是复制副本- -e
通常仅在开发软件包时使用。使用-e
,对python软件包文件(* .py)的更改将在您的pip环境中立即生效,而无需在每次更改后强制重新安装软件包。
cd foo && pip install -r ./bar/requirements.txt
它将在foo/bar
或中搜索setup.py foo
。如果是后者,有没有办法实现前者?
pip -r REQ
不在乎REQ所在的目录。即使您愿意,也可以从fifo馈送它pip install -r <(echo "mylib1"; echo "mylib2";)
。<(CMD)
bash命令替换在哪里,不是stdin重定向。
为了完整起见,以下是我从3 4个不同角度看待它的方法。
这是官方文档(重点是我的)中引用的精确描述:
尽管install_requires(在setup.py中)定义了单个项目的依赖关系,但“需求文件”通常用于定义完整Python环境的需求。
尽管install_requires需求最少,但是需求文件通常包含固定版本的详尽列表,目的是实现完整环境的可重复安装。
但是它可能仍然不容易理解,因此在下一节中,将提供2个事实示例,以不同的方式演示应如何使用这两种方法。
因此,它们的实际用法(应该是)不同
如果您的项目foo
将作为独立的库发布(意味着其他人可能会这样做import foo
),那么您(和下游用户)将希望有一个灵活的依赖声明,以使您的库不会(而且一定不能) )对您的依赖项的确切版本“保持警惕”。因此,通常,您的setup.py将包含以下行:
install_requires=[
'A>=1,<2',
'B>=2'
]
如果您只是想以某种方式为您的应用程序“记录”或“固定”您的EXACT当前环境bar
,这意味着您或您的用户希望bar
按原样使用您的应用程序,即运行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在他的博客文章中提到的一种方法。
下限不同。
即使遵循了以上3条条件,并正确地决定了您的库hybrid-engine
仍将使用a setup.py
声明其依赖关系engine>=1.2.0
,而示例应用程序reliable-car
仍将使用requirements.txt
其声明其依赖关系engine>=1.2.3
,即使最新版本的engine
1.4.0也是如此。如您所见,您对它们的下限数字的选择仍然略有不同。这就是为什么。
hybrid-engine
engine>=1.2.0
假设是因为,假设地,首先引入了所需的“内部燃烧”功能engine 1.2.0
,而该功能是必不可少的hybrid-engine
,而不管该版本内部是否存在某些(较小的)错误,并已在后续版本1.2.1中进行了修复。 ,1.2.2和1.2.3。
reliable-car
取决于,engine>=1.2.3
因为到目前为止,这是没有已知问题的最早版本。当然,以后的版本中会有新功能,例如引入了“电动机”和引入了engine 1.3.0
“核反应堆” engine 1.4.0
,但是对于项目而言,它们并不是必需的reliable-car
。
A==1.2.3
,然后如果库的下游程序包恰好依赖于A==1.2.4
,那么现在将无法同时满足这两个要求。最小化此冲突的解决方案是您的库定义一个已知的范围。假设semver.org之后已经有许多上游库,A>=1,<2
那么它将起作用。