requirements.txt vs setup.py

时间:2017-04-27 13:10:31

标签: python setup.py requirements.txt

我开始使用Python。我已将requirements.txtsetup.py添加到我的项目中。但是,我仍然对这两个文件的目的感到困惑。我已经读过setup.py是为可再发行的东西而设计的,requirements.txt是为不可再发行的东西而设计的。但我不确定这是否准确。

这两个文件真的打算如何使用?

3 个答案:

答案 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.txtdependencies-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.txtsetup.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个不同角度看待它的方式。

  1. 他们的设计目的不同

这是official documentation(强调我的名字)中引述的精确描述:

  

尽管install_requires(在setup.py中)定义了单个项目的依赖项,而需求文件通常用于定义完整的Python环境的需求。      

尽管install_requires需求很小,但是需求文件通常包含详尽的固定版本列表,目的是实现可重复安装的完整环境。

但是可能仍然不容易理解,因此在下一节中,将提供2个事实示例来演示应该如何以不同方式使用这两种方法。

  1. 因此,它们的实际用法(应该是)不同

    • 如果您的项目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
      
  2. 实际上,我该使用哪一个?

    • 如果您正在开发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中提到的一种方法。