Как установить отсутствующий пакет python из script, который ему нужен?
Предполагая, что у вас уже есть pip или easy_install, установленный в вашем дистрибутиве python, я хотел бы знать, как я могу установить требуемый пакет в каталог пользователя из самого script.
Из того, что я знаю, pip также является модулем python, поэтому решение должно выглядеть так:
try:
import zumba
except ImportError:
import pip
# ... do "pip install --user zumba" or throw exception <-- how?
import zumba
То, что мне не хватает, это сделать "pip install --user zumba" изнутри python, я не хочу делать это с помощью os.system()
, так как это может создать другие проблемы.
Я предполагаю, что это возможно...
Ответы
Ответ 1
Обновлено для более новой версии пипса (> = 10.0):
try:
import zumba
except ImportError:
from pip._internal import main as pip
pip(['install', '--user', 'zumba'])
import zumba
Благодаря @Joop я смог придумать правильный ответ.
try:
import zumba
except ImportError:
import pip
pip.main(['install', '--user', 'zumba'])
import zumba
Одним из важных замечаний является то, что это будет работать без корневого доступа, так как при этом модуль будет установлен в пользовательский каталог.
Не уверен, что он будет работать для двоичных модулей или модулей, требующих компиляции, но он явно работает хорошо для модулей с чистым питоном.
Теперь вы можете писать автономные скрипты и не беспокоиться о зависимостях.
Ответ 2
Начиная с версии pip> = 10.0.0, вышеприведенные решения не будут работать из-за внутренней реструктуризации пакетов. Новый способ использования pip внутри скрипта теперь выглядит следующим образом:
try: import abc
except ImportError:
from pip._internal import main as pip
pip(['install', '--user', 'abc'])
import abc
Ответ 3
Я хотел бы отметить, что текущий принятый ответ может привести к возможному столкновению имен приложений. Импорт из пространства имен приложений не дает вам полной информации о том, что установлено в системе.
Лучший способ:
import pip
packages = [package.project_name for package in pip.get_installed_distributions()]
if 'package' not in packages:
pip.main(['install', 'package'])