Überprüfen Sie, ob Python Package installiert ist


112

Wie kann überprüft werden, ob ein Paket in einem Python-Skript installiert ist? Ich weiß, dass es vom Dolmetscher einfach ist, aber ich muss es in einem Skript tun.

Ich denke, ich könnte überprüfen, ob es ein Verzeichnis auf dem System gibt, das während der Installation erstellt wurde, aber ich denke, es gibt einen besseren Weg. Ich versuche sicherzustellen, dass das Skype4Py-Paket installiert ist, und wenn nicht, werde ich es installieren.

Meine Ideen zur Durchführung der Prüfung

  • Suchen Sie nach einem Verzeichnis im typischen Installationspfad
  • Versuchen Sie, das Paket zu importieren. Wenn eine Ausnahme ausgelöst wird, installieren Sie das Paket

Schreiben eines Python-Skripts zur Automatisierung des Startens von Skype und Verwenden von tcpdump zum Sammeln von Paketdaten, damit ich analysieren kann, wie das Netzwerk funktioniert, wenn Sie eine Telefonkonferenz führen.
Kevin

Antworten:


106

Wenn Sie ein Python-Skript meinen, machen Sie einfach so etwas:

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
Warnung: Ich hatte heute gerade eine Situation, in der der ImportError in das Modul selbst geworfen wurde. Dies sollte nicht oft vorkommen, aber beachten Sie, dass diese Überprüfung nicht in allen Fällen zuverlässig ist.
Koen Bok

7
Dies überprüft nicht nur ; es importiert es auch; siehe auch stackoverflow.com/questions/14050281/…
Jorge Leitao

6
Ja. Das ist im Allgemeinen das, was Sie wollen. Sie können das Modul "Importtools" verwenden, um eine komplexere Prüfung durchzuführen. In den meisten Fällen ist es jedoch nur wichtig, dass Sie ein Modul installieren, weil Sie es verwenden möchten.
Christopher

Dies schlägt fehl, wenn Sie eine andere Datei mit demselben Namen wie das Paket haben.
Sapphire_Brick

55

Antwort aktualisiert

Ein besserer Weg, dies zu tun, ist:

import subprocess
import sys

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

Das Ergebnis:

print(installed_packages)

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

Überprüfen Sie, ob requestsinstalliert ist:

if 'requests' in installed_packages:
    # Do something

Warum so? Manchmal kommt es zu Kollisionen mit App-Namen. Beim Importieren aus dem App-Namespace erhalten Sie kein vollständiges Bild davon, was auf dem System installiert ist.

Beachten Sie, dass die vorgeschlagene Lösung funktioniert:

  • Bei Verwendung von pip zur Installation von PyPI oder einer anderen alternativen Quelle (wie pip install http://some.site/package-name.zipeinem anderen Archivtyp ).
  • Bei manueller Installation mit python setup.py install.
  • Bei der Installation aus System-Repositorys, wie z sudo apt install python-requests.

Fälle, in denen es möglicherweise nicht funktioniert:

  • Bei der Installation im Entwicklungsmodus wie python setup.py develop.
  • Bei der Installation im Entwicklungsmodus wie pip install -e /path/to/package/source/.

Alte Antwort

Ein besserer Weg, dies zu tun, ist:

import pip
installed_packages = pip.get_installed_distributions()

Für pip> = 10.x verwenden Sie:

from pip._internal.utils.misc import get_installed_distributions

Warum so? Manchmal kommt es zu Kollisionen mit App-Namen. Beim Importieren aus dem App-Namespace erhalten Sie kein vollständiges Bild davon, was auf dem System installiert ist.

Als Ergebnis erhalten Sie eine Liste von pkg_resources.DistributionObjekten. Sehen Sie sich als Beispiel Folgendes an:

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

Machen Sie eine Liste davon:

flat_installed_packages = [package.project_name for package in installed_packages]

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

Überprüfen Sie, ob requestsinstalliert ist:

if 'requests' in flat_installed_packages:
    # Do something

2
Wie in der anderen Antwort erwähnt, ist es möglich, dass der Fehler nicht abgefangen wird. Daher denke ich, dass dies die akzeptierte Antwort sein sollte.
Jorrick Sleijster

1
Diese Methode funktioniert nicht mit Paketen wie 'json' (gibt False zurück, wenn import jsontatsächlich funktioniert). Die Methode von ice.nicer funktioniert in diesem Fall.
mountrix

1
Irgendwie musste ich den Scheck if "u'requests'" in installed_packages:von Updated Answer verwenden, um für mich zu arbeiten. Die Ausgabe von print()erzeugt dies auf meinem macOS Python:[..., u'pytz', u'requests', ...]
Buju

1
@ArturBarseghyan Ich bin auf Python 2.7.10 (MacOS-System-Python) ... eigentlich muss ich verwenden if "requests'"(beachten Sie das einfache Anführungszeichen am Ende). macht überhaupt keinen Sinn.
Buju

1
Dies beantwortet nicht die Frage: "Ist das Paket 'x' installiert?". Es gibt viele Möglichkeiten, ein Paket ohne Verwendung zu installieren pip. Sie können beispielsweise ein Paket aus dem Quellcode erstellen und installieren. Diese Antwort wird diese nicht finden. Die Antwort von @ ice.nicer find_spec()ist richtig.
Arthur

41

Ab Python 3.3 können Sie die Methode find_spec () verwenden

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
Sauber und einfach, beste Antwort hier. Dies erfordert mehr Upvotes.
David Parks

5
Achtung. Wenn der Paketname Bindestriche enthält, kann find_spec () ihn nur finden, wenn Sie Punkte verwenden. Beispiel: importlib.util.find_spec('google-cloud-logging')Findet nichts, solange importlib.util.find_spec('google.cloud.logging')gefunden wird. Der offizielle Name und Name, den Pip anzeigt, ist mit Bindestrichen, nicht mit Punkten. Könnte verwirrend sein, daher mit Vorsicht verwenden.
Dwich

27

Wenn Sie die Prüfung vom Terminal aus erhalten möchten, können Sie sie ausführen

pip3 show package_name

und wenn nichts zurückgegeben wird, wird das Paket nicht installiert.

Wenn Sie diese Überprüfung möglicherweise automatisieren möchten, damit Sie sie beispielsweise installieren können, wenn sie fehlt, können Sie Folgendes in Ihr Bash-Skript einfügen:

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

Dies scheint großartig zu sein, gibt aber für mich immer "Nicht installiert" zurück. Warum?
Elliptica

Können Sie die Ausgabe von "$ pip3 - Version" und "$ pip3 show package_name" freigeben, wobei Sie package_name durch das gewünschte Paket ersetzen?
Ognjen Vukovic

Shell-Tipp: Sie können verwenden if, um einen erfolgreichen Befehl direkt zu testen:if pip3 show package_name 1>/dev/null; then ...
MestreLion

6

Als Erweiterung dieser Antwort :

Führt für Python 2. * pip show <package_name>dieselbe Aufgabe aus.

Zum Beispiel pip show numpywird Folgendes oder ähnliches zurückgegeben:

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

Nicht aus einem Skript, aber ideal für die Befehlszeilenprüfung. Vielen Dank
Jj Rivero

3

Sie können das Modul pkg_resources von setuptools verwenden. Beispielsweise:

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)

Beachten Sie, dass es einen Unterschied zwischen dem Python-Modul und einem Python-Paket gibt. Ein Paket kann mehrere Module enthalten, und die Namen der Module stimmen möglicherweise nicht mit dem Paketnamen überein.



1

Ich möchte diesem Thema einige meiner Gedanken / Erkenntnisse hinzufügen. Ich schreibe ein Skript, das alle Anforderungen für ein benutzerdefiniertes Programm überprüft. Es gibt auch viele Prüfungen mit Python-Modulen.

Es gibt ein kleines Problem mit dem

try:
   import ..
except:
   ..

Lösung. In meinem Fall hat eines der Python-Module aufgerufen python-nmap, aber Sie importieren es mit import nmapund wie Sie sehen, stimmen die Namen nicht überein. Daher gibt der Test mit der oben genannten Lösung ein falsches Ergebnis zurück und importiert das Modul bei einem Treffer, benötigt jedoch möglicherweise nicht viel Speicher für einen einfachen Test / eine einfache Überprüfung.

Das habe ich auch gefunden

import pip
installed_packages = pip.get_installed_distributions()

installed_packageswird haben nur die Pakete wurde mit pip installiert . Auf meinem System pip freezekehrt über 40Python-Module zurück, während installed_packagesnur 1das manuell installierte (python-nmap) vorhanden ist.

Eine andere Lösung, von der ich weiß, dass sie für die Frage möglicherweise nicht relevant ist , aber ich denke, es ist eine gute Praxis , die Testfunktion von der zu trennen , die die Installation durchführt, die für einige nützlich sein könnte.

Die Lösung, die für mich funktioniert hat. Basierend auf dieser Antwort So überprüfen Sie, ob ein Python-Modul vorhanden ist, ohne es zu importieren

from imp import find_module

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

HINWEIS: Diese Lösung kann das Modul auch nicht anhand des Namens python-nmapfinden. Ich muss es nmapstattdessen verwenden (einfach zu handhaben ), aber in diesem Fall wird das Modul überhaupt nicht in den Speicher geladen.


0

Wenn Sie möchten, dass Ihr Skript fehlende Pakete installiert und fortfährt, können Sie Folgendes tun (am Beispiel des Moduls 'krbV' im Paket '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

Eine schnelle Möglichkeit ist die Verwendung des Python- Befehlszeilentools. Einfach eingeben import <your module name> Sie sehen einen Fehler, wenn das Modul fehlt.

$ 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 ... das, was ich einer bequemen Antwort am nächsten kam, war die Verwendung der Befehlszeile, um den Import zu versuchen. Aber das vermeide ich lieber.

Wie wäre es mit 'Pip Freeze | grep pkgname '? Ich habe es versucht und es funktioniert gut. Es zeigt Ihnen auch die Version, die es hat, und ob es unter Versionskontrolle (Installation) oder bearbeitbar (Entwicklung) installiert ist.


0

Klasse myError (Ausnahme): pass #oder etwas tun versuchen: mymodule außer ImportError importieren als e: myError auslösen ("Fehler ist aufgetreten")


0

Im Terminaltyp

pip show some_package_name

Beispiel

pip show matplotlib

0

Ich möchte die Antwort von @ ice.nicer kommentieren, kann dies aber nicht. Meine Beobachtungen sind, dass Pakete mit Bindestrichen mit Unterstrichen gespeichert werden, nicht nur mit Punkten, wie im Kommentar von @dwich hervorgehoben

Zum Beispiel pip3 install sphinx-rtd-theme, aber:

  • importlib.util.find_spec(sphinx_rtd_theme) gibt ein Objekt zurück
  • importlib.util.find_spec(sphinx-rtd-theme) gibt None zurück
  • importlib.util.find_spec(sphinx.rtd.theme) löst ModuleNotFoundError aus

Außerdem werden einige Namen komplett geändert. Zum Beispiel tun Sie dies, pip3 install pyyamlaber es wird einfach als gespeichertyaml

Ich benutze Python3.8


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

-1

Gehen Sie zu Option 2. Wenn ImportErrores geworfen wird, ist das Paket nicht installiert (oder nicht in sys.path).

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.