setup_requires仅适用于某些命令

时间:2018-01-16 14:27:58

标签: python pip setuptools distutils

我有一个distutils风格的Python包,它需要一个特定的,非常大的依赖项来构建它。目前,此依赖关系是在distutils.setup的setup_requires参数下指定的。不幸的是,这意味着将为任何执行setup.py构建依赖关系,包括运行setup.py clean时。这造成了干净步骤的相当讽刺的情况,有时会导致编译大量代码。

正如我所说,只有build步骤才需要这种设置依赖性。有没有办法在setup.py中对此逻辑进行编码,以便所有不调用build命令的命令都可以在没有它的情况下运行?

2 个答案:

答案 0 :(得分:1)

if sys.argv[0] == 'build':
    kw = {'setup_requires': [req1, req2, …]}
else:
    kw = {}

setup(
    …,
    **kw
)

另一种尝试方法是使用自定义build覆盖cmdclass命令:

from setuptools.command.build import build as _build

class build(_build):
    def run(self):
        subprocess.call(["pip", "install", req1, req2…"])
        _build.run(self)

setup(
    …,
    cmdclass={'build': build},
)

并完全避免setup_requires

答案 1 :(得分:1)

您可以随时命令Distribution显式获取某些软件包,就像在setup_requires中定义它们时一样。仅numpy命令需要build依赖关系的示例:

from distutils.command.build import build as build_orig
from setuptools import setup, find_packages,  Command, dist


class build(build_orig):

    def run(self):
        self.distribution.fetch_build_eggs(['numpy'])
        # numpy becomes available after this line. Test it:
        import numpy
        print(numpy.__version__)
        super().run()

setup(
    name='spam',
    packages=find_packages(),
    cmdclass={'build': build,}
    ...
)

依赖项的传递方式与它们在setup_requires arg中定义的相同,因此版本规范也可以:

self.distribution.fetch_build_eggs(['numpy>=1.13'])

虽然我必须注意,通过setup_requires获取依赖项通常比通过pip安装它们要慢得多(尤其是当您有一些必须从源构建的重依赖项时)首先),如果您确定pip可用or use python3.4 and newer},phd在其answer中建议的方法可以节省您的时间。然而,在构建旧的python版本或模糊python安装(如MacOS上的系统python)时,通过分发获取egg可能会派上用场。