Vérifiez si le package Python est installé

113

Quel est un bon moyen de vérifier si un package est installé dans un script Python? Je sais que c'est facile avec l'interpréteur, mais je dois le faire dans un script.

Je suppose que je pourrais vérifier s'il y a un répertoire sur le système qui a été créé lors de l'installation, mais j'ai l'impression qu'il y a une meilleure façon. J'essaie de m'assurer que le package Skype4Py est installé, et sinon je l'installerai.

Mes idées pour effectuer le contrôle

  • rechercher un répertoire dans le chemin d'installation typique
  • essayez d'importer le package et si une exception est lancée, installez le package
Kevin
la source
Écrire un script Python pour automatiser le démarrage de Skype et utiliser tcpdump pour collecter des données de paquets afin que je puisse analyser le fonctionnement du réseau lorsque vous avez une conférence téléphonique.
Kevin le

Réponses:

108

Si vous voulez dire un script python, faites quelque chose comme ceci:

Python 3.3+ utilise sys.modules et 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.
Christophe
la source
6
Attention: je viens d'avoir une situation aujourd'hui où le ImportError a été jeté dans le module lui-même. Cela ne devrait pas arriver souvent, mais sachez simplement que ce contrôle n'est pas fiable dans tous les cas.
Koen Bok le
7
Cela ne veut pas seulement vérifier ; il l'importe également; voir aussi stackoverflow.com/questions/14050281/…
Jorge Leitao
6
Oui. C'est généralement ce que vous voulez. Vous pouvez utiliser le module d'outils d'importation pour effectuer une vérification plus sophistiquée, mais la plupart du temps, la seule raison pour laquelle vous vous souciez de l'installation d'un module est que vous souhaitez l'utiliser.
Christopher
Cela échouera si vous avez un autre fichier avec le même nom que le package.
Sapphire_Brick
Bien sûr, mais c'est un problème complètement différent. Si vous avez deux modules ou packages différents avec le même nom dans votre chemin de recherche, vous êtes en difficulté.
Christopher
56

Réponse mise à jour

Une meilleure façon de procéder est:

import subprocess
import sys

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

Le résultat:

print(installed_packages)

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

Vérifiez si requestsest installé:

if 'requests' in installed_packages:
    # Do something

Pourquoi de cette façon? Parfois, vous avez des collisions de noms d'applications. L'importation à partir de l'espace de noms de l'application ne vous donne pas une image complète de ce qui est installé sur le système.

Notez que la solution proposée fonctionne:

  • Lorsque vous utilisez pip pour installer à partir de PyPI ou de toute autre source alternative (comme pip install http://some.site/package-name.zipou tout autre type d'archive).
  • Lors de l'installation manuelle à l'aide de python setup.py install.
  • Lors de l'installation à partir de référentiels système, comme sudo apt install python-requests.

Cas où cela pourrait ne pas fonctionner:

  • Lors de l'installation en mode développement, comme python setup.py develop.
  • Lors de l'installation en mode développement, comme pip install -e /path/to/package/source/.

Ancienne réponse

Une meilleure façon de procéder est:

import pip
installed_packages = pip.get_installed_distributions()

Pour pip> = 10.x utilisez:

from pip._internal.utils.misc import get_installed_distributions

Pourquoi de cette façon? Parfois, vous avez des collisions de noms d'applications. L'importation à partir de l'espace de noms de l'application ne vous donne pas une image complète de ce qui est installé sur le système.

En conséquence, vous obtenez une liste d' pkg_resources.Distributionobjets. Voir l'exemple suivant:

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)",
]

Faites-en une liste:

flat_installed_packages = [package.project_name for package in installed_packages]

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

Vérifiez si requestsest installé:

if 'requests' in flat_installed_packages:
    # Do something
Artur Barseghyan
la source
2
Comme mentionné dans l'autre réponse, il est possible que l'erreur ne soit pas détectée. Par conséquent, je pense que cela devrait être la réponse acceptée.
Jorrick Sleijster
1
Cette méthode ne fonctionne pas avec des packages tels que 'json' (renvoie False quand import jsonfonctionne effectivement). La méthode de ice.nicer fonctionne dans ce cas.
mountrix
1
D'une certaine manière, j'avais besoin d'utiliser le chèque if "u'requests'" in installed_packages:de la réponse mise à jour pour travailler pour moi. La sortie de print()produit ceci sur mon python macOS:[..., u'pytz', u'requests', ...]
Buju
1
@ArturBarseghyan Je suis sur Python 2.7.10 (python système macOS) ... en fait je dois utiliser if "requests'"(notez le guillemet simple à la fin). n'a aucun sens.
Buju le
1
Cela ne répond pas à la question: "Le package 'x' est-il installé?". Il existe de nombreuses façons d'installer un package sans utiliser pip. Par exemple, vous pouvez créer et installer un package à partir des sources. Cette réponse ne les trouvera pas. La réponse de @ ice.nicer find_spec()est juste.
Arthur
43

Depuis Python 3.3, vous pouvez utiliser la méthode 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")
ice.nicer
la source
4
Propre et simple, meilleure réponse ici. Cela nécessite plus de votes positifs.
David Parks
5
Faites attention. Si le nom du paquet contient des tirets, find_spec () ne peut le trouver que si vous utilisez des points. Exemple: importlib.util.find_spec('google-cloud-logging')ne trouve rien tant qu'il importlib.util.find_spec('google.cloud.logging')est trouvé. Le nom officiel et le nom que pip montre sont avec des tirets, pas des points. Peut être déroutant, donc à utiliser avec prudence.
dwich
27

Si vous souhaitez avoir le chèque du terminal, vous pouvez exécuter

pip3 show package_name

et si rien n'est retourné, le package n'est pas installé.

Si vous souhaitez automatiser cette vérification, afin que par exemple vous puissiez l'installer en cas d'absence, vous pouvez avoir ce qui suit dans votre 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
Ognjen Vukovic
la source
Cela semble génial mais il renvoie toujours "Non installé" pour moi. Pourquoi?
Elliptica
Pouvez-vous partager la sortie de "$ pip3 —version" et "$ pip3 show package_name", où vous remplacez package_name par le package souhaité?
Ognjen Vukovic
ifif pip3 show package_name 1>/dev/null; then ...
Astuce
6

En prolongement de cette réponse :

Pour Python 2. *, pip show <package_name>effectuera la même tâche.

Par exemple pip show numpy, retournera ce qui suit ou similaire:

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
Ingénieur sans herpès
la source
Pas à partir d'un script mais idéal pour la vérification de la ligne de commande. Merci
Jj Rivero
3

Vous pouvez utiliser le module pkg_resources de setuptools. Par exemple:

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)

Notez qu'il existe une différence entre un module python et un package python. Un package peut contenir plusieurs modules et les noms de module peuvent ne pas correspondre au nom du package.

Lyudmil Nenov
la source
2

Ouvrez votre type d'invite de commande

pip3 list
Akhil G
la source
1

J'aimerais ajouter quelques réflexions / découvertes à ce sujet. J'écris un script qui vérifie toutes les exigences d'un programme personnalisé. Il existe également de nombreuses vérifications avec les modules python.

Il y a un petit problème avec le

try:
   import ..
except:
   ..

Solution. Dans mon cas, l'un des modules python est appelé python-nmap, mais vous l'importez avec import nmapet comme vous voyez que les noms ne correspondent pas. Par conséquent, le test avec la solution ci-dessus renvoie un résultat Faux, et il importe également le module lors de la frappe, mais peut-être pas besoin d'utiliser beaucoup de mémoire pour un simple test / vérification.

J'ai aussi trouvé que

import pip
installed_packages = pip.get_installed_distributions()

installed_packagesaura seulement les paquets a été installé avec pip . Sur mon système, pip freezeretourne sur les 40modules python, tandis que installed_packagesn'a que 1celui que j'ai installé manuellement (python-nmap).

Une autre solution ci-dessous dont je sais qu'elle n'est peut-être pas pertinente pour la question , mais je pense que c'est une bonne pratique de garder la fonction de test séparée de celle qui effectue l'installation, cela pourrait être utile pour certains.

La solution qui a fonctionné pour moi. Il est basé sur cette réponse Comment vérifier si un module python existe sans l'importer

from imp import find_module

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

REMARQUE: cette solution ne trouve pas non plus le module par son nom python-nmap, je dois l'utiliser à la nmapplace (facile à vivre) mais dans ce cas, le module ne sera pas chargé dans la mémoire du tout.

Gergely M
la source
0

Si vous souhaitez que votre script installe les packages manquants et continue, vous pouvez faire quelque chose comme ceci (sur l'exemple du module 'krbV' dans le package '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))
Alexandre Zhak
la source
0

Un moyen rapide consiste à utiliser l' outil de ligne de commande python . Tapez simplement import <your module name> Vous voyez une erreur si le module est manquant.

$ 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
$
Deepu Sahni
la source
0

Hmmm ... le plus proche que j'ai vu d'une réponse pratique était d'utiliser la ligne de commande pour essayer l'importation. Mais je préfère même éviter cela.

Que diriez-vous de «gel de pip grep pkgname '? Je l'ai essayé et ça marche bien. Il vous montre également la version dont il dispose et s'il est installé sous contrôle de version (installation) ou modifiable (développement).

Kim
la source
0

class myError (exception): passer #ou faire quelque chose essayer: importer mon module sauf ImportError comme e: lever myError ("une erreur s'est produite")

sh_mirzaee
la source
0

Dans le type de terminal

pip show some_package_name

Exemple

pip show matplotlib
Andreï
la source
0

Je voudrais commenter la réponse @ ice.nicer mais je ne peux pas, donc ... Mes observations sont que les paquets avec des tirets sont enregistrés avec des traits de soulignement, pas seulement avec des points comme indiqué par @dwich comment

Par exemple, vous le faites pip3 install sphinx-rtd-theme, mais:

  • importlib.util.find_spec(sphinx_rtd_theme) renvoie un objet
  • importlib.util.find_spec(sphinx-rtd-theme) renvoie Aucun
  • importlib.util.find_spec(sphinx.rtd.theme) lève ModuleNotFoundError

De plus, certains noms sont totalement modifiés. Par exemple, vous le faites pip3 install pyyamlmais il est enregistré simplement sousyaml

J'utilise python3.8

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

Allez l'option n ° 2. Si ImportErrorest levé, le package n'est pas installé (ou pas dans sys.path).

Eduffy
la source