setuptools setup.py fi中的install_requires kwarg的Reference requirements.txt

2024-05-15 16:55:46 发布

您现在位置:Python中文网/ 问答频道 /正文

我有一个与Travis CI一起使用的requirements.txt文件。复制requirements.txtsetup.py中的需求似乎很愚蠢,因此我希望将文件句柄传递给setuptools.setup中的install_requireskwarg。

这可能吗?如果是,我该怎么做呢?

这是我的requirements.txt文件:

guessit>=0.5.2
tvdb_api>=1.8.2
hachoir-metadata>=1.3.3
hachoir-core>=1.3.3
hachoir-parser>=1.3.4

Tags: install文件pytxttravisciapisetup
3条回答

它不能接受文件句柄。参数install_requires可以only be a string or a list of strings

当然,您可以读取安装脚本中的文件,并将其作为字符串列表传递给install_requires

import os
from setuptools import setup

with open('requirements.txt') as f:
    required = f.read().splitlines()

setup(...
install_requires=required,
...)

您可以将其翻转过来,在setup.py中列出依赖项,而在requirements.txt中使用一个字符-一个点.


或者,即使没有建议,也可以使用以下黑客(使用pip 9.0.1测试)解析requirements.txt文件(如果它没有通过URL引用任何外部需求):

install_reqs = parse_requirements('requirements.txt', session='hack')

但这不会过滤environment markers


在pip的旧版本中,更具体地说是older than 6.0,有一个公共API可以用来实现这一点。需求文件可以包含注释(#),也可以包含其他一些文件(--requirement-r)。因此,如果您真的想解析一个requirements.txt,可以使用pip解析器:

from pip.req import parse_requirements

# parse_requirements() returns generator of pip.req.InstallRequirement objects
install_reqs = parse_requirements(<requirements_path>)

# reqs is a list of requirement
# e.g. ['django==1.5.1', 'mezzanine==1.4.6']
reqs = [str(ir.req) for ir in install_reqs]

setup(
    ...
    install_requires=reqs
)

表面上看,似乎requirements.txtsetup.py是愚蠢的重复,但重要的是要理解,虽然形式相似,但预期的功能却截然不同。

当指定依赖项时,包作者的目标是说“无论您在何处安装此包,这些都是您需要的其他包,以便此包正常工作。”

相反,部署作者(在不同的时间可能是同一个人)有不同的工作,他们说“这里是我们收集和测试的包列表,我现在需要安装”。

软件包作者为各种各样的场景编写代码,因为他们把他们的工作放在那里,以他们可能不知道的方式使用,并且无法知道哪些软件包将与他们的软件包一起安装。为了成为一个好邻居并避免依赖版本与其他包冲突,它们需要指定尽可能多的依赖版本。这就是install_requires中的setup.py所做的。

部署作者为一个非常不同、非常具体的目标编写:安装在特定计算机上的已安装应用程序或服务的单个实例。为了精确控制部署,并确保测试和部署了正确的包,部署作者必须指定要安装的每个包的确切版本和源位置,包括依赖项和依赖项的依赖项。有了这个规范,一个部署可以重复地应用到多台机器上,或者在一台测试机器上测试,并且部署作者可以确信每次都部署相同的包。这就是requirements.txt所做的。

所以你可以看到,虽然它们看起来都是一个很大的包和版本列表,但这两个东西有着非常不同的工作。而且很容易把它弄错!但是正确的思考方式是requirements.txt是对所有不同setup.py包文件中的需求所提出的“问题”的“答案”。与其手动编写,它通常是通过告诉pip查看一组所需包中的所有setup.py文件,找到一组它认为符合所有要求的包,然后在安装后,将该包列表“冻结”到一个文本文件中(这是pip freeze名称的来源)。

所以外卖:

  • setup.py应该声明仍然可行的最宽松的依赖关系版本。它的工作是说明一个特定的包可以使用什么。
  • requirements.txt是定义整个安装作业的部署清单,不应将其视为绑定到任何一个包。它的工作是声明使部署工作所需的所有包的详尽列表。
  • 因为这两件事的内容和存在的原因是如此不同,所以简单地把一件复制到另一件是不可行的。

参考文献:

相关问题 更多 >