Установка модуля Python в коде

310

Мне нужно установить пакет из PyPi прямо в моем скрипте. Может быть, есть какой-то модуль или distutils( distributeи pipт. Д.) Функция, которая позволяет мне просто выполнить что-то подобное, pypi.install('requests')и запросы будут установлены в моем virtualenv.

chuwy
источник
4
Почему вы не определяете связанный модуль как зависимость в setup.py вашего собственного пакета?
Андреас Юнг
5
вы знаете ... как это на самом деле должно быть сделано ... но вы всегда можете использовать os.system ("pip install blah"), но вам может потребоваться доступ sudo ... лучше просто сделать его зависимым в вашей настройке. py
Joran Beasley
2
Вы бы хотели изменить принятый ответ здесь? Импорт pipникогда не был хорошей идеей - тот факт, что все его содержимое _internalначинается с версии 10 ...
Антти Хаапала
2
@chuwy stackoverflow.com/a/50255019/918959 <= этот. pip._internalне предназначен для импорта, он может делать абсолютно случайные вещи при импорте в другую программу.
Антти Хаапала
3
@AnttiHaapala хорошо, я изменил это. Мне лично не нравятся оба решения, но сейчас я далеко от Python, поэтому доверяю вашему мнению.
Чуви

Ответы:

255

Официально рекомендуемый способ установки пакетов из скрипта - вызов интерфейса командной строки pip через подпроцесс. Большинство других ответов, представленных здесь, не поддерживаются pip . Кроме того, начиная с pip v10, весь код был перемещен pip._internalточно, чтобы дать понять пользователям, что использование pip в программном обеспечении не разрешено.

Используйте, sys.executableчтобы убедиться, что вы будете вызывать то же самое, pipсвязанное с текущей средой выполнения.

import subprocess
import sys

def install(package):
    subprocess.check_call([sys.executable, "-m", "pip", "install", package])
Аарон де Виндт
источник
Одна из проблем заключается в том, что для начинающих пользователей в Windows python и pip не всегда находятся в своих PATH, и поэтому файл .py, который можно дважды щелкнуть, будет весьма удобным, тогда как комментарий «pip install xxx» может быть довольно сложно.
jdpipe
CalledProcessError: Команда '[' C: \\ ProgramData \\ Anaconda3 \\ pythonw.exe ',' -m ',' pip ',' install ',' googleapiclient ']' вернула ненулевой статус выхода 1.
Parvij,
383

Вы также можете использовать что-то вроде:

import pip

def install(package):
    if hasattr(pip, 'main'):
        pip.main(['install', package])
    else:
        pip._internal.main(['install', package])

# Example
if __name__ == '__main__':
    install('argh')
Рикард Англеруд
источник
3
@nbro вы передаете параметры так же, pip.main()как и в командной строке (но с каждым параметром в виде отдельной записи в списке вместо одной строки). И чтобы указать, какую версию пакета вы хотите, сделайте так же, как в командной строке .. например:pip.main(['install', 'pip==7.1.0'])
Kaos
3
См. Также stackoverflow.com/questions/6457794/… , в котором показано, как обращаться со случаем, когда происходит сбой установки.
П. Майер Нор
25
from pip._internal import main as pipmainтогда вы можете использовать так pipmain()же, как и устаревшие, pip.main()см. stackoverflow.com/questions/43398961/…
Бьоркс номер один вентилятор
17
его устарел сейчас.
Морс
6
Это не рекомендуется по причине и не рекомендуется больше. см. pip.pypa.io/en/latest/user_guide/#using-pip-from-your-program
НБК,
71

Если вы хотите использовать pipдля установки требуемый пакет и импортировать его после установки, вы можете использовать этот код:

def install_and_import(package):
    import importlib
    try:
        importlib.import_module(package)
    except ImportError:
        import pip
        pip.main(['install', package])
    finally:
        globals()[package] = importlib.import_module(package)


install_and_import('transliterate')

Если вы установили пакет как пользователь, вы можете столкнуться с проблемой, которую вы не можете просто импортировать. Смотрите Как обновить sys.path? для дополнительной информации.

rominf
источник
4
Есть идеи, как это сделать на Python 3? imp.reload(site)получает меняRuntimeError: dictionary changed size during iteration
kgadek
Где это установить пакет, после того, как я это сделал, я не смог сделать pip uninstall <package_name>. Я все еще могу удалить его, используя, pip.mainно просто хотел знать, где он устанавливает пакет?
Ишан Кхаре
Было любопытно. будет ли это работать правильно, если я сделаю pip install requests[security]:? Я не был уверен, правильно ли он определит глобалы.
Fallenreaper
4
Устаревшие. pip.mainбольше не работает. pip.pypa.io/en/latest/user_guide/#using-pip-from-your-program
wim
22

Это должно работать:

import subprocess

def install(name):
    subprocess.call(['pip', 'install', name])
квант
источник
1
Да, это определенно должно работать. Но я подумал, что есть более элегантный способ;) Я немного подожду, может быть, есть.
Чуви
1
@ Downvoter: Что именно не так с моим ответом? В этом ответе есть все, что хотел ОП. Он даже не использует оболочку.
квант
13
Это зависит от правильной версии пипса, который будет первым на пути. Если пользователь запускает альтернативную установку Python, pip будет установлен в первую, а не в текущую. Подход импорта выше установит в правильном месте. Я все равно проголосовал против голосования против.
GaryBishop
6
В зависимости от того, как работает скрипт, вы не назовете правильный пункт.
Натим,
5
Коллс [sys.executable, '-m', 'pip', 'install', name]гарантирует, что вы получите «правильный» пункт здесь.
Вим
12

я добавил некоторую обработку исключений в ответ @ Aaron.

import subprocess
import sys

try:
    import pandas as pd
except ImportError:
    subprocess.check_call([sys.executable, "-m", "pip", "install", 'pandas'])
finally:
    import pandas as pd
Сохан дас
источник
1
хорошая реализация подпроцесса и pip, лучше, чем большинство решений здесь
Shantanu Shady
3
Вы не проверяете значение retunr, subprocess.callпоэтому код может завершиться ошибкой.
Антти Хаапала
5

Вы определяете зависимый модуль внутри setup.py вашего собственного пакета с опцией «install_requires».

Если вашему пакету нужно сгенерировать какой-либо консольный скрипт, вы можете использовать точку входа «console_scripts», чтобы сгенерировать скрипт-обертку, который будет помещен в папку «bin» (например, вашей среды virtualenv).

Андреас Юнг
источник
1
Это правильный ответ и единственный разумный способ управления зависимостями проектов Python. Это будет работать с virtualenv, Fabric, buildout, вы называете это. Метод, описанный @xiaomao, хотя и отвечает точно на то, что спросил ОП, - это чистое безумие.
Лукас Граф
7
хотя это правильный совет, он не отвечает на заданный вопрос
Кори Голдберг
2
Хотя упаковка является темой, существует много других вариантов использования, например сценарий развертывания, написанный на python.
ворчу