Instalar el módulo de Python dentro del código

310

Necesito instalar un paquete desde PyPi directamente dentro de mi script. Tal vez hay alguna función de módulo o distutils( distribute, pipetc.) que me permite ejecutar algo así pypi.install('requests')y las solicitudes se instalarán en mi virtualenv.

chuwy
fuente
44
¿Por qué no define el módulo relacionado como dependencia en el setup.py de su propio paquete?
Andreas Jung
55
ya sabes ... la forma en que se supone que se debe hacer ... pero siempre puedes usar os.system ("pip install blah") pero es posible que necesites acceso a sudo ... mejor solo para que sea una dependencia en tu configuración. py
Joran Beasley
2
¿Consideraría cambiar la respuesta aceptada aquí? Importar pipnunca es una buena idea: el mero hecho de que todo su contenido esté en la _internalversión 10 ...
Antti Haapala
2
@chuwy stackoverflow.com/a/50255019/918959 <= este. pip._internalno está diseñado para ser importable, puede hacer cosas absolutamente al azar cuando se importa en otro programa.
Antti Haapala
3
@AnttiHaapala está bien, lo cambié. Personalmente no me gustan ambas soluciones, pero estoy lejos de Python en estos días, así que confío en tu opinión.
chuwy

Respuestas:

255

La forma oficialmente recomendada de instalar paquetes desde un script es llamando a la interfaz de línea de comandos de pip a través de un subproceso. La mayoría de las otras respuestas presentadas aquí no son compatibles con pip . Además, desde pip v10, todo el código se ha movido apip._internal precisamente para dejar en claro a los usuarios que el uso programático de pip no está permitido.

Úselo sys.executablepara asegurarse de que invocará lo mismo pipasociado con el tiempo de ejecución actual.

import subprocess
import sys

def install(package):
    subprocess.check_call([sys.executable, "-m", "pip", "install", package])
Aaron de Windt
fuente
Un problema con esto es que, para usuarios novatos en Windows, python y pip no siempre están en su RUTA, por lo que un archivo .py al que se pueda hacer doble clic sería bastante conveniente, mientras que un comentario "pip install xxx" puede ser bastante complicado
jdpipe
CalledProcessError: el comando '[' C: \\ ProgramData \\ Anaconda3 \\ pythonw.exe ',' -m ',' pip ',' install ',' googleapiclient ']' devolvió el estado de salida no cero 1.
parvij
383

También puedes 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
fuente
3
@nbro pasa las opciones pip.main()como lo haría en la línea de comando (pero con cada opción como una entrada separada en la lista, en lugar de una sola cadena). Y para especificar qué versión del paquete desea, haga lo mismo que en la línea de comando. Ej:pip.main(['install', 'pip==7.1.0'])
Kaos
3
Consulte también stackoverflow.com/questions/6457794/… , que muestra cómo manejar el caso donde falla una instalación.
P. Myer Nore
25
from pip._internal import main as pipmainentonces puedes usarlo pipmain()como el obsoleto pip.main()ver stackoverflow.com/questions/43398961/…
Fan número uno de Bjorks
17
es depreceated ahora.
Morse
66
Está en desuso por una razón y ya no se recomienda. ver pip.pypa.io/en/latest/user_guide/#using-pip-from-your-program
NBK
71

Si desea usar pippara instalar el paquete requerido e importarlo después de la instalación, puede 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')

Si instaló un paquete como usuario, puede encontrar el problema de que no puede simplemente importar el paquete. Consulte ¿Cómo actualizar sys.path? para informacion adicional.

rominf
fuente
44
¿Alguna idea de cómo hacer eso en Python 3? imp.reload(site)me RuntimeError: dictionary changed size during iteration
atrapa
¿dónde instala esto el paquete? Después de hacer esto, no pude hacerlo pip uninstall <package_name>. Todavía puedo desinstalarlo usando, pip.mainpero solo quería saber dónde instala el paquete.
Ishan Khare
Tenía curiosidad ¿funcionaría esto correctamente si lo hago pip install requests[security]:? No estaba seguro de si definiría correctamente los globales correctamente.
Fallenreaper
44
Anticuado. pip.mainYa no funciona. pip.pypa.io/en/latest/user_guide/#using-pip-from-your-program
wim
22

Esto debería funcionar:

import subprocess

def install(name):
    subprocess.call(['pip', 'install', name])
cuántico
fuente
1
Sí, definitivamente debería funcionar. Pero pensé que hay una forma más elegante;) Estaré esperando un poco, puede que haya.
chuwy
1
@Downvoter: ¿Qué tiene de malo exactamente mi respuesta? Esta respuesta tiene todo el OP deseado. Ni siquiera usa un caparazón.
Quantum
13
Depende de que la versión correcta de pip sea la primera en el camino. Si el usuario está ejecutando una instalación alternativa de python, pip se instalará en la primera en lugar de la actual. El enfoque de importación anterior se instalará en el lugar correcto. He votado de todos modos para contrarrestar el voto negativo.
GaryBishop
66
Dependiendo de cómo se ejecute el script, no llamarás al pip correcto.
Natim
55
Llamar [sys.executable, '-m', 'pip', 'install', name]es asegurarse de obtener el pip "correcto" aquí.
wim
12

Agregué algo de manejo de excepciones a la respuesta de @ 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
fuente
1
Buena implementación de subprocesos y pip, mejor que la mayoría de las soluciones aquí
Shantanu Shady
3
No está comprobando el valor de retunr de subprocess.callmodo que el código podría fallar.
Antti Haapala
5

Usted define el módulo dependiente dentro de setup.py de su propio paquete con la opción "install_requires".

Si su paquete necesita que se genere algún script de consola, puede usar el punto de entrada "console_scripts" para generar un script de envoltura que se colocará dentro de la carpeta 'bin' (por ejemplo, de su entorno virtualenv).

Andreas Jung
fuente
1
Esta es la respuesta correcta y la única forma sensata de administrar las dependencias de un proyecto Python. Funcionará con virtualenv, Fabric, buildout, lo que sea. El método descrito por @xiaomao, a pesar de responder exactamente lo que preguntó el OP, es pura locura.
Lukas Graf
77
Si bien este es un consejo adecuado, no responde a la pregunta formulada
Corey Goldberg
2
Si bien el empaquetado es un tema, existen muchos otros casos de uso, por ejemplo, un script de implementación escrito en python.
hoefling 02 de