Установить по умолчанию "необязательные" зависимости в Python (setuptools)

Есть ли способ указать необязательные зависимости для пакета Python, который должен быть установлен по умолчанию из pip но для которого установка не должна рассматриваться как сбой, если они не могут быть установлены?

Я знаю что могу уточнить install_requires так что пакеты будут установлены для 90% пользователей, использующих операционные системы, которые могут легко установить определенные дополнительные зависимости, и я также знаю, что могу указать extra_require чтобы указать, что пользователи могут заявить, что они хотят полную установку, чтобы получить эти функции, но я не нашел способа сделать по умолчанию pip установить попробуйте установить пакеты, но не жалуйтесь, если они не могут быть установлены.

(Конкретный пакет, который я хотел бы обновить setuptools а также setup.py для называется music21 для которых 95% инструментов могут быть запущены без matplotlib, IPython, scipy, pygame, некоторых неясных аудио инструментов и т. д., но пакет приобретает дополнительные возможности и скорость, если эти пакеты установлены, и я бы предпочел, чтобы люди имели эти возможности по умолчанию, но не сообщать об ошибках, если они не могут быть установлены)

2 ответа

В любом случае, это не идеальное решение, но вы можете настроить скрипт после установки, чтобы попытаться установить пакеты, что-то вроде этого:

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,
    },
)

Самый простой способ сделать это - добавить пользовательскую команду установки, которая просто отправляет команду 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).

Это может быть то, что вы ищете. Похоже, это встроенная функция инструментов настройки, которая позволяет объявлять "необязательные зависимости".

https://setuptools.readthedocs.io/en/latest/setuptools.html

бывший

setup(
    name="Project-A",
    ...
    extras_require={
        'PDF':  ["ReportLab>=1.2", "RXP"],
        'reST': ["docutils>=0.3"],
    }
)
Другие вопросы по тегам