默认安装Python中的“可选”依赖项(setuptools)

时间:2018-11-19 13:53:51

标签: python pip setuptools music21

是否可以为应该从pip 默认安装的Python包指定可选的依赖关系,但是如果无法安装,则不应认为安装失败?

我知道我可以指定install_requires,以便使用可以轻松安装某些可选依赖项的操作系统为90%的用户安装软件包,并且我也可以指定extra_require指定用户可以声明他们想要完整安装以获得这些功能,但是我还没有找到一种方法来进行默认的pip安装尝试安装软件包,但没有抱怨如果无法安装。

(我想为其更新setuptoolssetup.py的特定软件包称为music21,其中95%的工具都可以在没有matplotlib,IPython,scipy, pygame,一些晦涩的音频工具等,但是如果安装了这些程序包,则该程序包会获得额外的功能和速度,我希望默认情况下让人们拥有这些功能,但如果无法安装,则不报告错误)

3 个答案:

答案 0 :(得分:5)

无论如何都不是完美的解决方案,但是您可以设置一个安装后脚本来尝试安装软件包,如下所示:

from distutils.core import setup
from distutils import debug


from setuptools.command.install import install
class PostInstallExtrasInstaller(install):
    extras_install_by_default = ['matplotlib', 'nothing']

    @classmethod
    def pip_main(cls, *args, **kwargs):
        def pip_main(*args, **kwargs):
            raise Exception('No pip module found')
        try:
            from pip import main as pip_main
        except ImportError:
            from pip._internal import main as pip_main

        ret = pip_main(*args, **kwargs)
        if ret:
            raise Exception(f'Exitcode {ret}')
        return ret

    def run(self):
        for extra in self.extras_install_by_default:
            try:
                self.pip_main(['install', extra])
            except Exception as E:
                print(f'Optional package {extra} not installed: {E}')
            else:
                print(f"Optional package {extra} installed")
        return install.run(self)


setup(
    name='python-package-ignore-extra-dep-failures',
    version='0.1dev',
    packages=['somewhat',],
    license='Creative Commons Attribution-Noncommercial-Share Alike license',
    install_requires=['requests',],
    extras_require={
        'extras': PostInstallExtrasInstaller.extras_install_by_default,
    },
    cmdclass={
        'install': PostInstallExtrasInstaller,
    },
)

答案 1 :(得分:2)

最简单的方法是添加一个自定义安装命令,该命令只需将pShell打包成pip即可安装“可选”软件包。在您的setup.py中:

import sys
import subprocess
from setuptools import setup
from setuptools.command.install import install

class MyInstall(install):
    def run(self):
        subprocess.call([sys.executable, "-m", "pip", "install", "whatever"])
        install.run(self)

setup(
    ...

    cmdclass={
        'install': MyInstall,
    },
)

就像上面的hoefling一样,如果您发布源代码发布(.tar.gz.zip),这将有效。如果您将软件包发布为内置发行版(.whl),它将无法正常工作。

答案 2 :(得分:0)

这可能是您要寻找的。它似乎是设置工具的内置功能,可让您声明“可选依赖项”。

https://setuptools.readthedocs.io/en/latest/setuptools.html#declaring-extras-optional-features-with-their-own-dependencies

Ex

setup(
    name="Project-A",
    ...
    extras_require={
        'PDF':  ["ReportLab>=1.2", "RXP"],
        'reST': ["docutils>=0.3"],
    }
)