Wie überprüfe ich, ob ein Python-Modul importiert wurde?

87

Wie überprüfe ich, ob ich irgendwo im Code ein Modul importiert habe?

 if not has_imported("somemodule"):
     print('you have not imported somemodule')

Der Grund, warum ich überprüfen möchte, ob ich bereits ein Modul importiert habe, ist, dass ich ein Modul habe, das ich nicht importieren möchte, weil es manchmal mein Programm durcheinander bringt.

Yuval
quelle
Fügen Sie einfach raise SystemError()(oder eine andere Ausnahme Ihrer Wahl) oben in das Modul ein, das Sie nicht importieren möchten. Wenn Sie es tatsächlich irgendwo importieren, wird Ihr Programm einen Traceback auslösen und beenden.
Larsks
Wie bringt das Importieren eines Moduls Ihr Programm überhaupt durcheinander? Klingt nicht so wahrscheinlich.
Bill Woodger
1
@ BillWoodger: Vielleicht ändert dieses Modul den globalen Status, den Sie nicht ändern möchten .
Martijn Pieters
@MartijnPieters Yoiks. Und Import klingt so neutral.
Bill Woodger

Antworten:

118

Testen Sie den Modulnamen im sys.modulesWörterbuch :

import sys

modulename = 'datetime'
if modulename not in sys.modules:
    print 'You have not imported the {} module'.format(modulename)

Aus der Dokumentation:

Dies ist ein Wörterbuch, das Modulnamen bereits geladenen Modulen zuordnet.

Beachten Sie, dass eine importAnweisung zwei Dinge tut:

  1. Wenn das Modul noch nie importiert wurde (== nicht vorhanden in sys.modules), wird es geladen und hinzugefügt sys.modules.
  2. Binden Sie einen oder mehrere Namen im aktuellen Namespace, die auf das Modulobjekt verweisen, oder an Objekte, die Mitglieder des Modul-Namespace sind.

Der Ausdruck modulename not in sys.modulestestet, ob Schritt 1 stattgefunden hat. Um das Ergebnis von Schritt 2 zu testen, muss bekannt sein, welche genaue importAnweisung verwendet wurde, da unterschiedliche Namen festgelegt wurden, um auf verschiedene Objekte zu verweisen:

  • import modulename setzt modulename = sys.modules['modulename']
  • import packagename.nestedmoduleSätze packagename = sys.modules['packagename'](egal wie viele zusätzliche Ebenen Sie hinzufügen)
  • import modulename as altname setzt altname = sys.module['modulename']
  • import packagename.nestedmodule as altname setzt altname = sys.modules['packagename.nestedmodule']
  • from somemodule import objectname setzt objectname = sys.modules['somemodule'].objectname
  • from packagename import nestedmodulenameSets nestedmodulename = sys.modules['packagename.nestedmodulename'](nur wenn vor diesem Import kein Objekt nestedmodulenameim packagenameNamespace benannt wurde, wird zu diesem Zeitpunkt ein zusätzlicher Name für das verschachtelte Modul zum Namespace des übergeordneten Pakets hinzugefügt)
  • from somemodule import objectname as altname setzt altname = sys.modules['somemodule'].objectname
  • from packagename import nestedmodulename as altnameSets altname = sys.modules['packagename.nestedmodulename'](nur wenn vor diesem Import kein Objekt nestedmodulenameim packagenameNamespace benannt wurde, wird zu diesem Zeitpunkt ein zusätzlicher Name für das verschachtelte Modul zum Namespace des übergeordneten Pakets hinzugefügt)

Sie können testen, ob der Name, an den das importierte Objekt gebunden wurde, in einem bestimmten Namespace vorhanden ist:

# is this name visible in the current scope:
'importedname' in dir()

# or, is this a name in the globals of the current module:
'importedname' in globals()

# or, does the name exist in the namespace of another module:
'importedname' in globals(sys.modules['somemodule'])

Dies sagt Ihnen nur, dass der Name existiert (gebunden wurde), nicht, wenn er sich auf ein bestimmtes Modul oder Objekt aus diesem Modul bezieht. Sie können dieses Objekt weiter untersuchen oder testen, ob es dasselbe Objekt ist wie das, in dem es verfügbar ist sys.modules, wenn Sie ausschließen müssen, dass der Name seitdem vollständig auf etwas anderes festgelegt wurde.

Martijn Pieters
quelle
1
Ist dies der beste Weg, um innerhalb einer Funktion nach einem erforderlichen Paket zu suchen? Das heißt, für einige Funktionen ist ein numpyPaket erforderlich. Ist die Verwendung import sysinnerhalb der Funktion am besten geeignet, um zu überprüfen, ob sie importiert wurde? Mit "am besten" meine ich die Auswirkungen auf die Leistung import sys, die dann bei jedem Aufruf der Funktion aufgerufen werden. Vielen Dank
Confounded
@Confounded können Sie einfach sys außerhalb der Funktion importieren, wenn Sie sich Sorgen machen. Nicht, dass import sysdas in irgendeiner Weise teuer wäre; sysexistiert immer, es ist standardmäßig schon geladen. Aber für ein optionales Paket: Importieren Sie einfach das Paket . Fangen Sie die ImportErrorAusnahme ab, wenn das Paket nicht installiert ist, und setzen Sie ein Flag, das angibt, dass es installiert ist, wenn der Import erfolgreich ist. Danach können Sie das Flag verwenden, um Ihre Verwendung über die optionale Abhängigkeit zu informieren.
Martijn Pieters
@Confounded Der name in sys.modulesTest ist nur nützlich, wenn Sie nicht importieren möchten .
Martijn Pieters
23

Zu den akzeptierten Antworten von sys.modules möchte ich eine Einschränkung hinzufügen, um beim Umbenennen von Modulen beim Import vorsichtig zu sein:

>>> import sys
>>> import datetime as dt
>>> 'dt' in sys.modules
False
>>> 'datetime' in sys.modules
True
morvan68
quelle
18

Verwenden Sie sys.modules, um zu testen, ob ein Modul importiert wurde (ich verwende Unicodedata als Beispiel):

>>> import sys
>>> 'unicodedata' in sys.modules
False
>>> import unicodedata
>>> 'unicodedata' in sys.modules
True
Haresh Shyara
quelle
4

sys.modules Enthält alle Module, die an einer beliebigen Stelle in der aktuellen Instanz des Interpreters verwendet werden, und wird angezeigt, wenn sie in ein anderes Python-Modul importiert werden.

dir() prüft, ob der Name im aktuellen Namespace definiert wurde.

Die Kombination der beiden ist sicherer als jede einzelne und funktioniert so lange, wie Sie selbst keine definiert haben copy.

if ('copy' in sys.modules) and ('copy' in dir()):
HansW
quelle
-1
if "sys" not in dir():
  print("sys not imported!")
rundekugel
quelle
Dadurch wird nur geprüft, ob das Modul in den aktuellen Namespace importiert wurde. Auch syskann alles, nicht nur ein Modul sein.
Vaultah