Compruebe si el paquete Python está instalado


112

¿Cuál es una buena forma de comprobar si un paquete está instalado dentro de un script de Python? Sé que es fácil para el intérprete, pero necesito hacerlo dentro de un guión.

Supongo que podría verificar si hay un directorio en el sistema que se creó durante la instalación, pero siento que hay una mejor manera. Estoy tratando de asegurarme de que el paquete Skype4Py esté instalado y, si no, lo instalaré.

Mis ideas para realizar el chequeo

  • busque un directorio en la ruta de instalación típica
  • intente importar el paquete y si se lanza una excepción, instale el paquete

Escribir un script de Python para automatizar el inicio de Skype y usar tcpdump para recopilar datos de paquetes para poder analizar cómo funciona la red cuando tienes una llamada de conferencia.
Kevin

Respuestas:


107

Si te refieres a un script de Python, simplemente haz algo como esto:

Python 3.3+ usa sys.modules y find_spec :

import importlib.util
import sys

# For illustrative purposes.
name = 'itertools'

if name in sys.modules:
    print(f"{name!r} already in sys.modules")
elif (spec := importlib.util.find_spec(name)) is not None:
    # If you choose to perform the actual import ...
    module = importlib.util.module_from_spec(spec)
    sys.modules[name] = module
    spec.loader.exec_module(module)
    print(f"{name!r} has been imported")
else:
    print(f"can't find the {name!r} module")

Python 3:

try:
    import mymodule
except ImportError as e:
    pass  # module doesn't exist, deal with it.

Python 2:

try:
    import mymodule
except ImportError, e:
    pass  # module doesn't exist, deal with it.

6
Advertencia: Acabo de tener una situación hoy en la que se lanzó ImportError dentro del módulo en sí. Esto no debería suceder a menudo, pero tenga en cuenta que esta verificación no es confiable en todos los casos.
Koen Bok

7
Esto no solo comprueba ; también lo importa; ver también stackoverflow.com/questions/14050281/…
Jorge Leitao

6
Si. Eso es generalmente lo que quieres. Puede usar el módulo de herramientas de importación para hacer una verificación más sofisticada, pero la mayoría de las veces la única razón por la que le importa si un módulo está instalado es porque desea usarlo.
Christopher

Esto fallará si tiene otro archivo con el mismo nombre que el paquete.
Sapphire_Brick

Claro, pero ese es un problema completamente diferente. Si tiene dos módulos o paquetes diferentes con el mismo nombre en su ruta de búsqueda, tiene problemas.
Christopher

56

Respuesta actualizada

Una mejor forma de hacer esto es:

import subprocess
import sys

reqs = subprocess.check_output([sys.executable, '-m', 'pip', 'freeze'])
installed_packages = [r.decode().split('==')[0] for r in reqs.split()]

El resultado:

print(installed_packages)

[
    "Django",
    "six",
    "requests",
]

Compruebe si requestsestá instalado:

if 'requests' in installed_packages:
    # Do something

¿Por qué de esta manera? A veces tienes colisiones de nombres de aplicaciones. Importar desde el espacio de nombres de la aplicación no le brinda una imagen completa de lo que está instalado en el sistema.

Tenga en cuenta que la solución propuesta funciona:

  • Al usar pip para instalar desde PyPI o desde cualquier otra fuente alternativa (como pip install http://some.site/package-name.zipo cualquier otro tipo de archivo).
  • Al instalar manualmente usando python setup.py install.
  • Al instalar desde repositorios del sistema, como sudo apt install python-requests.

Casos en los que podría no funcionar:

  • Al instalar en modo de desarrollo, me gusta python setup.py develop.
  • Al instalar en modo de desarrollo, me gusta pip install -e /path/to/package/source/.

Respuesta antigua

Una mejor forma de hacer esto es:

import pip
installed_packages = pip.get_installed_distributions()

Para pip> = 10.x use:

from pip._internal.utils.misc import get_installed_distributions

¿Por qué de esta manera? A veces tienes colisiones de nombres de aplicaciones. Importar desde el espacio de nombres de la aplicación no le brinda una imagen completa de lo que está instalado en el sistema.

Como resultado, obtienes una lista de pkg_resources.Distributionobjetos. Vea lo siguiente como ejemplo:

print installed_packages
[
    "Django 1.6.4 (/path-to-your-env/lib/python2.7/site-packages)",
    "six 1.6.1 (/path-to-your-env/lib/python2.7/site-packages)",
    "requests 2.5.0 (/path-to-your-env/lib/python2.7/site-packages)",
]

Haz una lista:

flat_installed_packages = [package.project_name for package in installed_packages]

[
    "Django",
    "six",
    "requests",
]

Compruebe si requestsestá instalado:

if 'requests' in flat_installed_packages:
    # Do something

2
Como se menciona en la otra respuesta, es posible que no se detecte el error. Por tanto, creo que esta debería ser la respuesta aceptada.
Jorrick Sleijster

1
Este método no funciona con paquetes como 'json' (devuelve False cuando import jsonestá funcionando). El método de ice.nicer está funcionando en este caso.
mountrix

1
De alguna manera, necesitaba usar el cheque if "u'requests'" in installed_packages:de Respuesta actualizada para que funcionara para mí. La salida de print()produce esto en mi macOS python:[..., u'pytz', u'requests', ...]
Buju

1
@ArturBarseghyan Estoy en Python 2.7.10 (macOS system python) ... en realidad tengo que usar if "requests'"(observe la comilla simple al final). no tiene ningún sentido.
Buju

1
Esto no responde a la pregunta: "¿está instalado el paquete 'x'?". Hay muchas formas de instalar un paquete sin usar pip. Por ejemplo, puede crear e instalar un paquete desde la fuente. Esta respuesta no los encontrará. La respuesta de @ ice.nicer find_spec()es correcta.
Arthur

43

A partir de Python 3.3, puede usar el método find_spec ()

import importlib.util

# For illustrative purposes.
package_name = 'pandas'

spec = importlib.util.find_spec(package_name)
if spec is None:
    print(package_name +" is not installed")

4
Limpio y simple, la mejor respuesta aquí. Esto necesita más votos a favor.
David Parks

5
Ten cuidado. Si el nombre del paquete contiene guiones, find_spec () no puede encontrarlo a menos que use puntos. Ejemplo: importlib.util.find_spec('google-cloud-logging')no encuentra nada mientras importlib.util.find_spec('google.cloud.logging')se encuentra. El nombre oficial y el nombre que muestra pip es con guiones, no con puntos. Puede resultar confuso, por lo tanto, utilícelo con precaución.
Dwich

27

Si desea tener el cheque desde la terminal, puede ejecutar

pip3 show package_name

y si no se devuelve nada, el paquete no está instalado.

Si quizás desea automatizar esta verificación, de modo que, por ejemplo, pueda instalarlo si falta, puede tener lo siguiente en su script bash:

pip3 show package_name 1>/dev/null #pip for Python 2
if [ $? == 0 ]; then
   echo "Installed" #Replace with your actions
else
   echo "Not Installed" #Replace with your actions, 'pip3 install --upgrade package_name' ?
fi

Esto parece genial, pero siempre me devuelve "No instalado". ¿Por qué?
Elliptica

¿Puede compartir la salida de “$ pip3 —version” y “$ pip3 show package_name”, donde reemplaza package_name con el paquete deseado?
Ognjen Vukovic

ifif pip3 show package_name 1>/dev/null; then ...
Consejo de

6

Como una extensión de esta respuesta :

Para Python 2. *, pip show <package_name>realizará la misma tarea.

Por ejemplo pip show numpy, devolverá lo siguiente o similar:

Name: numpy
Version: 1.11.1
Summary: NumPy: array processing for numbers, strings, records, and objects.
Home-page: http://www.numpy.org
Author: NumPy Developers
Author-email: numpy-discussion@scipy.org
License: BSD
Location: /home/***/anaconda2/lib/python2.7/site-packages
Requires: 
Required-by: smop, pandas, tables, spectrum, seaborn, patsy, odo, numpy-stl, numba, nfft, netCDF4, MDAnalysis, matplotlib, h5py, GridDataFormats, dynd, datashape, Bottleneck, blaze, astropy

No de un script, pero es genial para la verificación de la línea de comandos. Gracias
Jj Rivero

3

Puede utilizar el módulo pkg_resources de setuptools. Por ejemplo:

import pkg_resources

package_name = 'cool_package'
try:
    cool_package_dist_info = pkg_resources.get_distribution(package_name)
except pkg_resources.DistributionNotFound:
    print('{} not installed'.format(package_name))
else:
    print(cool_package_dist_info)

Tenga en cuenta que existe una diferencia entre el módulo de Python y un paquete de Python. Un paquete puede contener varios módulos y es posible que los nombres de los módulos no coincidan con el nombre del paquete.



1

Me gustaría agregar algunos pensamientos / hallazgos míos a este tema. Estoy escribiendo un script que verifica todos los requisitos para un programa personalizado. También hay muchas comprobaciones con los módulos de Python.

Hay un pequeño problema con el

try:
   import ..
except:
   ..

solución. En mi caso python-nmap, se llamó a uno de los módulos de Python , pero lo importas con import nmapy cuando ves que los nombres no coinciden. Por lo tanto, la prueba con la solución anterior devuelve un resultado falso, y también importa el módulo en el momento del impacto, pero tal vez no sea necesario utilizar mucha memoria para una prueba / verificación simple.

Tambien encontre que

import pip
installed_packages = pip.get_installed_distributions()

installed_packagessolo tendrá los paquetes que se hayan instalado con pip . En mi sistema, pip freezedevuelve los 40módulos de Python, mientras que installed_packagessolo tiene 1el que instalé manualmente (python-nmap).

Otra solución a continuación que sé que puede no ser relevante para la pregunta , pero creo que es una buena práctica mantener la función de prueba separada de la que realiza la instalación, podría ser útil para algunos.

La solución que funcionó para mí. Se basa en esta respuesta Cómo verificar si existe un módulo de Python sin importarlo

from imp import find_module

def checkPythonmod(mod):
    try:
        op = find_module(mod)
        return True
    except ImportError:
        return False

NOTA: esta solución no puede encontrar el módulo por el nombre python-nmaptambién, tengo que usarlo nmapen su lugar (fácil de vivir) pero en este caso el módulo no se cargará en la memoria en absoluto.


0

Si desea que su script instale los paquetes que faltan y continúe, puede hacer algo como esto (en el ejemplo del módulo 'krbV' en el paquete 'python-krbV'):

import pip
import sys

for m, pkg in [('krbV', 'python-krbV')]:
    try:
        setattr(sys.modules[__name__], m, __import__(m))
    except ImportError:
        pip.main(['install', pkg])
        setattr(sys.modules[__name__], m, __import__(m))

0

Una forma rápida es usar la herramienta de línea de comandos de Python . Simplemente escriba import <your module name> . Verá un error si falta el módulo.

$ python
Python 2.7.6 (default, Jun 22 2015, 17:58:13) 
>>> import sys
>>> import jocker
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ImportError: No module named jocker
$

0

Hmmm ... lo más cercano que vi a una respuesta conveniente fue usar la línea de comando para probar la importación. Pero prefiero incluso evitar eso.

¿Qué tal 'pip freeze | grep pkgname '? Lo probé y funciona bien. También te muestra la versión que tiene y si está instalada bajo control de versiones (instalar) o editable (desarrollar).


0

clase myError (excepción): pase # o haga algo intente: importar mymodule excepto ImportError como e: raise myError ("se produjo un error")


0

En el tipo de Terminal

pip show some_package_name

Ejemplo

pip show matplotlib

0

Me gustaría comentar la respuesta de @ ice.nicer pero no puedo, así que ... Mis observaciones son que los paquetes con guiones se guardan con guiones bajos, no solo con puntos como lo señala el comentario de @dwich

Por ejemplo, lo hace pip3 install sphinx-rtd-theme, pero:

  • importlib.util.find_spec(sphinx_rtd_theme) devuelve un objeto
  • importlib.util.find_spec(sphinx-rtd-theme) devuelve Ninguno
  • importlib.util.find_spec(sphinx.rtd.theme) genera ModuleNotFoundError

Además, algunos nombres están totalmente cambiados. Por ejemplo, lo hace, pip3 install pyyamlpero se guarda simplemente comoyaml

Estoy usando python3.8


0
if pip3 list | grep -sE '^some_command\s+[0-9]' >/dev/null
  # installed ...
else
  # not installed ...
fi

-1

Vaya a la opción # 2. Si ImportErrorse lanza, el paquete no está instalado (o no está incluido sys.path).

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.