我有一个我正在使用Travis-CI的requirements.txt文件。在requirements.txt和setup.py中复制需求似乎很愚蠢,所以我希望在setuptools.setup中传递一个文件句柄给install_requires kwarg。

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

这是我的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

当前回答

小心parse_requirements行为!

请注意,pip.req。Parse_requirements将把下划线改为破折号。这件事让我生气了几天,后来我才发现。示例演示:

from pip.req import parse_requirements  # tested with v.1.4.1

reqs = '''
example_with_underscores
example-with-dashes
'''

with open('requirements.txt', 'w') as f:
    f.write(reqs)

req_deps = parse_requirements('requirements.txt')
result = [str(ir.req) for ir in req_deps if ir.req is not None]
print result

生产

['example-with-underscores', 'example-with-dashes']

其他回答

虽然这不是问题的确切答案,但我推荐Donald Stufft在https://caremad.io/2013/07/setup-vs-requirement/上的博客文章,它很好地回答了这个问题。我用它取得了巨大的成功。

简而言之,requirements.txt不是setup.py的替代品,而是部署的补充。在setup.py中保持包依赖关系的适当抽象。设置requirements.txt或更多的文件,以获取用于开发、测试或生产的软件包依赖关系的特定版本。

例如,在deps/下的回购中包含包:

# fetch specific dependencies
--no-index
--find-links deps/

# install package
# NOTE: -e . for editable mode
.

PIP执行包的setup.py并安装在install_requires中声明的依赖项的特定版本。没有表里不一,这两件文物的用途都被保留了下来。

小心parse_requirements行为!

请注意,pip.req。Parse_requirements将把下划线改为破折号。这件事让我生气了几天,后来我才发现。示例演示:

from pip.req import parse_requirements  # tested with v.1.4.1

reqs = '''
example_with_underscores
example-with-dashes
'''

with open('requirements.txt', 'w') as f:
    f.write(reqs)

req_deps = parse_requirements('requirements.txt')
result = [str(ir.req) for ir in req_deps if ir.req is not None]
print result

生产

['example-with-underscores', 'example-with-dashes']

交叉张贴我从这个SO问题的答案,另一个简单的,pip版本证明解决方案。

try:  # for pip >= 10
    from pip._internal.req import parse_requirements
    from pip._internal.download import PipSession
except ImportError:  # for pip <= 9.0.3
    from pip.req import parse_requirements
    from pip.download import PipSession

requirements = parse_requirements(os.path.join(os.path.dirname(__file__), 'requirements.txt'), session=PipSession())

if __name__ == '__main__':
    setup(
        ...
        install_requires=[str(requirement.req) for requirement in requirements],
        ...
    )

然后把所有的需求放在项目根目录下的requirements.txt下。

它不能接受文件句柄。install_requires参数只能是字符串或字符串列表。

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

import os
from setuptools import setup

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

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

上面的大多数其他答案都不能与当前版本的pip API一起使用。下面是使用pip当前版本(撰写本文时为6.0.8,在7.1.2中也有效)的正确*方法。您可以使用pip -V检查您的版本。

from pip.req import parse_requirements
from pip.download import PipSession

install_reqs = parse_requirements(<requirements_path>, session=PipSession())

reqs = [str(ir.req) for ir in install_reqs]

setup(
    ...
    install_requires=reqs
    ....
)

正确,因为这是当前pip使用parse_requirements的方式。这仍然可能不是最好的方法,因为正如上面的帖子所说,pip并没有真正维护API。