如何在安装过程中指定setup.py需要的依赖项?

18
在某些情况下,setup.py需要导入一些额外的模块,例如:
from setuptools import setup
import foo

setup(
    # e.g. a keyword uses `foo`
    version=foo.generate_version()
)

如果没有安装foo,执行setup.py将会因为ImportError而失败。

我已经尝试使用setup_requires,例如setup_requires=['foo'],但是无济于事。

那么如何指定这种依赖关系呢?


1
使用 setup_requires 是正确的,但是你不能在设置脚本的顶部导入列在 setup_requires 中的包。你需要导入什么?如果你导入 foo 来组装 setup() 函数的输入参数,那么你就没有机会在设置脚本中管理这个依赖关系;否则,覆盖命令应该是答案。请展示你的设置脚本。 - hoefling
5个回答

10

pyproject.toml 允许指定自定义构建工具:

[build-system]
requires = [..., foo, ...]
build-backend = "setuptools.build_meta"

6
我想出了一个诀窍 - 在setup.py中调用pip来安装依赖项。
import pip
pip.main(['install', 'foo', 'bar'])    # call pip to install them

# Now I can import foo & bar
import foo, bar
from setuptools import setup

setup(
    ...
)

5

setup.py文件中不能指定所需的依赖项。在运行python setup.py之前,必须先安装它们:

pip install -r requirements.txt
python setup.py install

2

就像 @Tosha 回答的那样,pyproject.toml 是你的好朋友。

以下是我项目中使用 jinja2 的一个示例:

setup.py: # 简化 - 移除了所有实际代码

import jinja2
from setuptools import setup

setup(name='test')

使用命令 python -m build --wheel 进行构建会出现问题:
* Creating venv isolated environment...
* Installing packages in isolated environment... (setuptools >= 40.8.0, wheel)
* Getting dependencies for wheel...
Traceback (most recent call last):
  File "/tmp/venv/lib/python3.6/site-packages/pep517/in_process/_in_process.py", line 363, in <module>
    main()
  File "/tmp/venv/lib/python3.6/site-packages/pep517/in_process/_in_process.py", line 345, in main
    json_out['return_val'] = hook(**hook_input['kwargs'])
  File "/tmp/venv/lib/python3.6/site-packages/pep517/in_process/_in_process.py", line 130, in get_requires_for_buil
d_wheel
    return hook(config_settings)
  File "/tmp/build-env-4zi79uth/lib/python3.6/site-packages/setuptools/build_meta.py", line 163, in get_requires_fo
r_build_wheel
    config_settings, requirements=['wheel'])
  File "/tmp/build-env-4zi79uth/lib/python3.6/site-packages/setuptools/build_meta.py", line 143, in _get_build_requ
ires
    self.run_setup()
  File "/tmp/build-env-4zi79uth/lib/python3.6/site-packages/setuptools/build_meta.py", line 268, in run_setup
    self).run_setup(setup_script=setup_script)
  File "/tmp/build-env-4zi79uth/lib/python3.6/site-packages/setuptools/build_meta.py", line 158, in run_setup
    exec(compile(code, __file__, 'exec'), locals())
  File "setup.py", line 1, in <module>
    import jinja2
ModuleNotFoundError: No module named 'jinja2'

ERROR Backend subproccess exited when trying to invoke get_requires_for_build_wheel

然而,添加一个pyproject.toml文件:
[build-system]
requires = [
    "setuptools",
    "jinja2",
]

修复了这个问题

注意:我也包括setuptools作为要求。忽略它也会导致错误。


0

我有一个类似的问题,我想从yaml文件中获取安装程序的版本,因此我需要解析它并从中获取版本。

我使用以下脚本作为答案:

#!/usr/bin/env python

from setuptools import setup
import yaml


def find_version():
    with open('meta/main.yml') as meta_main:
        return yaml.load(meta_main)['version']


setup(name='sample',
      version=find_version(),
      packages=[],
      setup_requires=['pyyaml'])

我发现setup方法具有setup_requires参数,可以指定安装设置依赖项。如setuptools文档中所述,在setup_requires中列出的项目将不会自动安装在运行setup脚本的系统上。如果您想要它们被安装,并在运行设置脚本时可用,您应该将它们添加到install_requiressetup_requires中。

如果您有任何其他问题,请告诉我。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接