Установить по умолчанию "необязательные" зависимости в 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"],
}
)