setup_requires только для некоторых команд
У меня есть пакет Python в стиле distutils, который требует определенной и довольно большой зависимости для этапа сборки. В настоящее время эта зависимость указана под setup_requires
аргумент к distutils.setup. К сожалению, это означает, что зависимость будет построена для любого выполнения setup.py, в том числе при запуске setup.py clean
, Это создает довольно ироничную ситуацию с чистым шагом, иногда вызывающим компиляцию большого количества кода.
Как я уже сказал, эта зависимость установки требуется только для build
шаг. Есть ли способ закодировать эту логику в setup.py, чтобы все команды, которые не вызывают команду сборки, выполнялись без нее?
2 ответа
Вы всегда можете заказать 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
доступно ( или использовать python3.4
и новее), подход, предложенный phd в его ответе, сэкономит ваше время. Однако выборка яиц через дистрибутив может оказаться полезной при сборке для старых версий python или неясных установок python, таких как системный python в MacOS.
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
совсем.