Как мне обрабатывать импорт сторонних библиотек в моем сценарии setup.py?

Я разрабатываю приложение Python и в процессе выпуска релиза. У меня есть сервер PyPI, настроенный на сервере компании, и я скопировал на него исходный дистрибутив своего пакета.

Я проверил, что пакет размещается на сервере, а затем попытался установить его на свой локальный компьютер для разработки. Я закончил с этим выводом:

$ pip3 install --trusted-host 172.16.1.92 -i http://172.16.1.92:5001/simple/ <my-package>
Collecting <my-package>
  Downloading http://172.16.1.92:5001/packages/<my-package>-0.2.0.zip
    Complete output from command python setup.py egg_info:
    Traceback (most recent call last):
      File "<string>", line 1, in <module>
      File "C:\Users\<me>\AppData\Local\Temp\pip-build-ubb3jkpr\<my-package>\setup.py", line 9, in <module>
        import appdirs
    ModuleNotFoundError: No module named 'appdirs'

    ----------------------------------------
Command "python setup.py egg_info" failed with error code 1 in C:\Users\<me>\AppData\Local\Temp\pip-build-ubb3jkpr\<my-package>\

Причина в том, что я пытаюсь импортировать стороннюю библиотеку appdirs в свой setup.py, которая необходима мне для вычисления аргумента data_files в setup():

try:
    from setuptools import setup
except ImportError:
    from distutils.core import setup

import os
from collections import defaultdict

import appdirs
from <my-package>.version import __version__ as <my-package>_version

APP_NAME = '<my-app>'
APP_AUTHOR = '<company>'
SYSTEM_COMPONENT_PLUGIN_DIR = os.path.join(appdirs.user_data_dir(APP_NAME, APP_AUTHOR), 'components')

# ...

setup(
    # ...
    data_files=component_files,
)

Однако у меня не установлено appdirs на моей локальной машине разработки, и я не ожидаю, что оно будет установлено и у конечных пользователей.

Допустимо ли полагаться на сторонние библиотеки, подобные этой, в setup.py, и если да, то каков рекомендуемый подход к их использованию? Есть ли способ убедиться, что appdirs будет установлен до того, как он будет импортирован в setup.py, или я должен просто задокументировать, что appdirs является обязательным пакетом для установки моего пакета?


person Tagc    schedule 01.06.2017    source источник
comment
Вы пробовали использовать setup_requires? См. pip.readthedocs.io/en/1.4.1. /   -  person Peter Brittain    schedule 04.06.2017
comment
@PeterBrittain Есть ли примеры того, как его использовать? Должен ли я сделать что-то вроде двух вызовов setup(), один в верхней части setup.py только с setup_requires=['appdirs'], а другой уже внизу?   -  person Tagc    schedule 05.06.2017
comment
Это не обычно... Вы можете найти простой пример в stackoverflow.com /questions/37471313/setup-requires-with-cython. Это начинает показывать виды обручей, упомянутых в python.org/dev/peps/pep. -0518, который выделяет другую возможность сделать это с помощью pip, которая должна быть доступна в ближайшее время.   -  person Peter Brittain    schedule 06.06.2017


Ответы (3)


Я игнорирую вопросы лицензирования в этом ответе. Вам определенно нужно принять это во внимание, прежде чем вы действительно сделаете релиз.

Допустимо ли полагаться на сторонние библиотеки, подобные этой, в setup.py?

Да, это приемлемо, но, как правило, их следует сводить к минимуму, особенно если это модули, которые не имеют очевидной пользы для конечного пользователя. Никто не любит иметь пакеты, которые им не нужны или не используются.

каков рекомендуемый подход к их использованию?

Есть в основном 3 варианта:

person MSeifert    schedule 04.06.2017
comment
Похоже, что appdirs имеет лицензию MIT, поэтому второй вариант кажется наиболее привлекательным. В идеале setup_requires (который рекомендует @PeterBrittain) выглядит как лучшее решение, но я не совсем уверен, как его использовать. - person Tagc; 05.06.2017
comment
Ну, это зависит от лицензии, размера, стабильности и от того, нужна ли она вам как зависимость от времени выполнения, чтобы решить, какой подход является наиболее привлекательным. Мне лично не нравится setup_requires, потому что это раздражает (невозможно) использовать с некоторыми способами локальной установки пакета (я думаю, что python setup.py install, python setup.py develop или pip install . не подойдут). - person MSeifert; 06.06.2017
comment
appdirs, похоже, странно разрешает пути при запуске в качестве локального модуля, поэтому я выбрал третий вариант. - person Tagc; 06.06.2017

Вы можете использовать pip для программной установки пакета в случае сбоя import:

try:
    import appdirs
except ImportError:
    import pip
    pip.main(['install', 'appdirs'])
    import appdirs

В некоторых случаях вам может понадобиться использовать importlib или __import__ для импорта пакета после pip.main или ссылаться на переменную PATH. Также может быть полезно включить проверку, действительно ли пользователь хочет установить этот пакет перед его установкой.

Я использовал много примеров из "Установка модуля Python в коде" и лично не пробовал использовать это в setup.py файлы, но похоже, что это может быть решением вашего вопроса.

person MSeifert    schedule 06.06.2017
comment
Мне любопытно, почему за это проголосовали. Это кажется безболезненным и функциональным решением проблемы, с которой я столкнулся лично. - person Chris Allen Lane; 07.02.2019

Вы можете указать install_requires в списке зависимостей. Ознакомьтесь с руководством по упаковке Python здесь. Также вы можете предоставить файл requirements.txt, чтобы его можно было запустить сразу, используя «pip install -r».

person Venu    schedule 04.06.2017
comment
Я не уверен, как install_requires поможет, вы имели в виду setup_requires? Однако, по моему опыту, это сложно сделать правильно. Особенно, если нельзя гарантировать, что setuptools установлен, а try: from setuptools import setup не гарантируется. - person MSeifert; 04.06.2017
comment
Если я не ошибаюсь, setup_requires просто загружает зависимости, но install_requires устанавливает их, я согласен, что инструменты установки должны быть импортированы. - person Venu; 05.06.2017
comment
@Venu: можно требовать setuptools для установки вашего пакета. Если вы используете pip для установки, setuptools уже входит в комплект. Я бы просто использовал здесь setuptools и setup_requires. - person Martijn Pieters; 05.06.2017