Instalando o módulo python no código

310

Preciso instalar um pacote do PyPi diretamente no meu script. Talvez haja algum módulo ou recurso distutils( distribute, pipetc.) que permita executar algo como pypi.install('requests')e solicitações serão instaladas no meu virtualenv.

chuwy
fonte
4
Por que você não define o módulo relacionado como dependência no setup.py do seu próprio pacote?
Andreas Jung
5
você sabe ... do jeito que realmente deveria ser feito ... mas você sempre pode usar o os.system ("pip install blah"), mas pode precisar de acesso ao sudo ... melhor para torná-lo uma dependência na sua configuração. py
Joran Beasley
2
Você consideraria alterar a resposta aceita aqui? Importando pipnunca é uma boa ideia - o simples facto de todo o seu conteúdo estão _internalna partir da versão 10 ...
Antti Haapala
2
@chuwy stackoverflow.com/a/50255019/918959 <= este. pip._internalnão foi projetado para ser importável, ele pode fazer coisas absolutamente aleatórias quando importado em outro programa.
Antti Haapala
3
@AnttiHaapala ok, eu mudei. Pessoalmente, não gosto das duas soluções, mas hoje estou longe do Python, por isso confio na sua opinião.
chuwy

Respostas:

254

A maneira oficialmente recomendada de instalar pacotes a partir de um script é chamando a interface da linha de comandos do pip por meio de um subprocesso. A maioria das outras respostas apresentadas aqui não são suportadas pelo pip . Além disso, desde o pip v10, todo o código foi movido parapip._internal precisamente para deixar claro aos usuários que o uso programático do pip não é permitido.

Use sys.executablepara garantir que você chamará o mesmo pipassociado ao tempo de execução atual.

import subprocess
import sys

def install(package):
    subprocess.check_call([sys.executable, "-m", "pip", "install", package])
Aaron de Windt
fonte
Um problema é que, para usuários iniciantes no Windows, python e pip nem sempre estão em seu PATH; portanto, um arquivo .py que pode ser clicado duas vezes seria bastante conveniente, enquanto um comentário "pip install xxx" pode ser bastante complicado.
jdpipe 17/04
CalledProcessError: Command '[' C: \ ProgramData \\ Anaconda3 \\ pythonw.exe ',' -m ',' pip ',' install ',' googleapiclient ']' retornou o status de saída diferente de zero 1.
parvij
383

Você também pode usar algo como:

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')
Rikard Anglerud
fonte
3
@ nbro você passa as opções pip.main()como faria na linha de comando (mas com cada opção como uma entrada separada na lista, em vez de uma única string). E para especificar qual versão do pacote você deseja, faça o mesmo que na linha de comando .. ex:pip.main(['install', 'pip==7.1.0'])
Kaos
3
Consulte também stackoverflow.com/questions/6457794/… , que mostra como lidar com o caso em que uma instalação falha.
P. Myer Nore
25
from pip._internal import main as pipmainentão você pode usar pipmain()exatamente como o obsoleto, pip.main()veja stackoverflow.com/questions/43398961/…
Bjorks number one fan
17
está depreciado agora.
Morse
6
Ele foi descontinuado por um motivo e não é mais recomendado. consulte pip.pypa.io/en/latest/user_guide/#using-pip-from-your-program
NBK
71

Se você deseja usar pippara instalar o pacote necessário e importá-lo após a instalação, você pode usar este código:

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')

Se você instalou um pacote como usuário, poderá encontrar o problema de que não pode apenas importar o pacote. Consulte Como atualizar o sys.path? para informações adicionais.

rominf
fonte
4
Alguma idéia de como fazer isso no Python 3? imp.reload(site)me recebeRuntimeError: dictionary changed size during iteration
kgadek
Onde isso instala o pacote? Depois que eu fiz isso, não consegui fazer pip uninstall <package_name>. Ainda posso desinstalá-lo usando, pip.mainmas só queria saber onde ele instala o pacote?
Ishan Khare
Estava curioso. isso funcionaria corretamente se eu fizer pip install requests[security]:? Eu não tinha certeza se definiria corretamente os globais corretamente.
Fallenreaper
4
Desatualizado. pip.mainnão funciona mais. pip.pypa.io/en/latest/user_guide/#using-pip-from-your-program
wim
23

Isso deve funcionar:

import subprocess

def install(name):
    subprocess.call(['pip', 'install', name])
quantum
fonte
1
Sim, definitivamente deve funcionar. Mas eu pensei que havia um jeito mais elegante;) vou ficar esperando um pouquinho, pode ser que exista.
chuwy
1
@ Downowner: O que exatamente está errado com a minha resposta? Essa resposta tem todo o OP desejado. Nem sequer usa uma concha.
quantum
13
Depende da versão correta do pip ser a primeira no caminho. Se o usuário estiver executando uma instalação python alternativa, o pip será instalado na primeira em vez da atual. A abordagem de importação acima será instalada no lugar certo. Eu votei de qualquer maneira para contrariar a votação.
precisa saber é o seguinte
6
Dependendo de como o script está sendo executado, você não chamará o pip certo.
Natim
5
Ligar [sys.executable, '-m', 'pip', 'install', name]é garantir o pip "certo" aqui.
Wim
12

Eu adicionei algumas exceções à resposta do @ 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
Sohan Das
fonte
1
agradável implementação de subprocesso e pip, melhor do que a maioria das soluções aqui
Shantanu Shady
3
Você não está verificando o valor de retorno subprocess.callpara que o código possa falhar.
Antti Haapala
5

Você define o módulo dependente dentro do setup.py do seu próprio pacote com a opção "install_requires".

Se o seu pacote precisar ter algum script do console gerado, você poderá usar o ponto de entrada "console_scripts" para gerar um script de wrapper que será colocado na pasta 'bin' (por exemplo, do seu ambiente de virtualenv).

Andreas Jung
fonte
1
Esta é a resposta correta e a única maneira sensata de gerenciar as dependências de um projeto Python. Ele funcionará com virtualenv, Fabric, buildout, etc. O método descrito por @xiaomao, mesmo respondendo exatamente ao que o OP pediu, é pura loucura.
Lukas Graf
7
Embora este seja um conselho adequado, ele não responde à pergunta
Corey Goldberg
2
Embora o empacotamento seja um tópico, existem muitos outros casos de uso, por exemplo, um script de implantação escrito em python.
hoefling