我开始使用Python。我已将要求.txt
和 setup.py
添加到我的项目中。但是,我仍然对这两个文件的目的感到困惑。我已经读到 setup.py
是为可再发行的东西而设计的,而需求.txt
是为不可再发行的东西设计的。但我不确定这是否准确。
这两个文件真正打算如何使用?
为了完整起见,以下是我从
3
4 个不同角度看待它的方式。
这是从官方文件中引用的精确描述(强调我的):
install_requires(setup.py)定义单个项目的依赖关系,而需求文件通常用于定义完整Python环境的需求。
尽管install_requires需求很少,但需求文件通常包含一个详尽的固定版本列表,目的是实现完整环境的可重复安装。
但是它可能仍然不容易被理解,所以在下一节中,有两个实际的例子来演示这两种方法应该如何被不同地使用。
>
如果您的项目foo
将作为一个独立库发布(这意味着,其他人可能会导入foo<-code>),那么您(以及您的下游用户)将希望有一个灵活的依赖声明,这样您的库就不会(而且一定不会)“挑剔”依赖的确切版本。所以,通常是您的设置。py将包含如下行:
install_requires=[
'A>=1,<2',
'B>=2'
]
如果您只是想以某种方式“记录”或“固定”您的应用程序< code>bar
的确切当前环境,也就是说,您或您的用户希望按原样使用您的应用程序< code>bar,即运行< code>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
,即使这是“为了好玩而编写脚本”,仍然建议您使用需求。因为,谁知道,下周(正好是圣诞节)你会收到一台新电脑作为礼物,所以你需要在那里重新设置确切的环境。
如果您正在开发一个将由< code>import foo使用的库< code>foo,您必须准备一个setup.py. Period。但是您仍然可以选择同时提供一个requirements.txt,它可以:
(A)属于< code>A==1.2.3型(如上文#2所述);
(b)或仅包含神奇的单曲。
.
后者本质上是使用传统的< code>requirements.txt习惯来记录您的安装步骤是< code>pip install。,意思是“基于setup.py安装需求”而不重复。就我个人而言,我认为最后一种方法模糊了界限,增加了混乱,但它仍然是在CI环境中运行时明确选择不进行依赖关系锁定的一种方便的方法。这个技巧源自Python打包维护者Donald在他的博客文章中提到的一种方法。
不同的下限。
假设存在具有此历史记录的现有< code >引擎库:
engine 1.1.0 Use steam
...
engine 1.2.0 Internal combustion is invented
engine 1.2.1 Fix engine leaking oil
engine 1.2.2 Fix engine overheat
engine 1.2.3 Fix occasional engine stalling
engine 2.0.0 Introducing nuclear reactor
您遵循了以上3个标准,并正确地决定了您的新库<code>混合引擎</code>将使用<code>设置。py</code>声明其依赖性<code>引擎
>
混合动力发动机
取决于engine
可靠-汽车
依赖引擎
简而言之,requirements.txt
仅用于列出包需求。setup.py
另一方面更像是安装脚本。如果您不打算安装python代码,通常您只需要requirements.txt
。
文件< code>setup.py除了描述包依赖关系之外,还描述了应该打包(或编译,在本机模块的情况下(即,用C编写))的文件和模块集,以及要添加到python包列表中的元数据(例如,包名、包版本、包描述、作者,...).
因为两个文件都列出了依赖项,这可能会导致一些重复。详情请阅读下文。
requirements.txt
这个文件列出了python包的需求。它是一个纯文本文件(可选地带有注释),列出了python项目的包依赖项(每行一个)。它没有描述python包的安装方式。您通常会使用< code > pip install-r requirements . txt 来使用需求文件。
文本文件的文件名是任意的,但是按照惯例通常是< code>requirements.txt。在探索其他python包的源代码库时,您可能会偶然发现其他名称,例如< code > dev-dependencies . txt 或< code > dependencies-dev . txt 。这些与< code>dependencies.txt的目的相同,但通常列出特定包的开发人员感兴趣的附加依赖项,即用于测试源代码(例如pytest、pylint等。)发布前。包的用户通常不需要整个开发者依赖集来运行包。
如果存在多个< code>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 。
我真的需要两者吗?
简短的回答是否定的,但两者兼而有之真是太好了。它们实现不同的目的,但它们都可用于列出依赖项。
您可以考虑一个技巧来避免在需求.txt
和 setup.py
之间重复依赖关系列表。如果您已经为包编写了一个完全工作 setup.py
,并且您的依赖项大多是外部的,则可以考虑制定一个简单的要求.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安装
选项,它以可编辑模式安装给定的包。当<code>pip-r要求时。txt</code>在此文件上运行,pip将通过<code>./setup.py</code>中的列表安装依赖项。可编辑选项将在安装目录中放置一个符号链接(而不是鸡蛋或存档副本)。它允许开发人员在不重新安装的情况下从存储库中就地编辑代码。
当您的包存储库中同时拥有两个文件时,您还可以利用所谓的“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,例如那些用< code>virtualenv程序创建的沙箱。这将避免在项目开发环境之外安装python包。
要求.txt
:
这有助于您设置开发环境。
像< code>pip这样的程序可以用来一次性安装文件中列出的所有软件包。之后,您可以开始开发您的python脚本。如果您计划让其他人参与开发或使用虚拟环境,这尤其有用。这是你如何使用它:
pip install -r requirements.txt
它可以通过pip
自身轻松生成:
pip freeze > requirements.txt
pip
会自动尝试仅添加默认情况下未安装的包,因此生成的文件非常少。
setup.py
:
这有助于您创建可以重新分发的包。
setup.py
脚本旨在将软件包安装在最终用户的系统上,而不是像 pip install -r 要求
那样准备开发环境.txt。有关 setup.py
的更多详细信息,请参阅此答案。
项目的依赖项在两个文件中都列出。