Comment vérifier si un module python a été importé?

91

Comment vérifier si j'ai importé un module quelque part dans le code?

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

La raison pour laquelle je voudrais vérifier si j'ai déjà importé un module est que j'ai un module que je ne veux pas importer parce que parfois cela gâche mon programme.

Yuval
la source
Mettez simplement raise SystemError()(ou toute autre exception de votre choix) en haut du module que vous ne souhaitez pas importer. Si vous n'importez réellement quelque part, votre programme va jeter un retraçage et de sortie.
larsks
Comment le simple fait d'importer un module perturbe-t-il votre programme? Cela ne semble pas si probable.
Bill Woodger
1
@BillWoodger: peut-être que ce module change l'état global que vous ne voulez pas changer .
Martijn Pieters
@MartijnPieters Yoiks. Et importer des sons si neutres.
Bill Woodger
Possible duplication de la façon de tester si un module python a été importé?
shadowtalker

Réponses:

122

Testez le nom du module dans le sys.modulesdictionnaire :

import sys

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

De la documentation:

Il s'agit d'un dictionnaire qui mappe les noms de modules aux modules qui ont déjà été chargés.

Notez qu'une importinstruction fait deux choses:

  1. si le module n'a jamais été importé auparavant (== non présent dans sys.modules), alors il est chargé et ajouté à sys.modules.
  2. Liez un ou plusieurs noms dans l'espace de noms actuel qui référencent l'objet module ou aux objets qui sont membres de l'espace de noms du module.

L'expression modulename not in sys.modulesteste si l'étape 1 a eu lieu. Le test du résultat de l'étape 2 nécessite de savoir quelle importinstruction exacte a été utilisée car ils définissent des noms différents pour référencer différents objets:

  • import modulename ensembles modulename = sys.modules['modulename']
  • import packagename.nestedmoduleensembles packagename = sys.modules['packagename'](quel que soit le nombre de niveaux supplémentaires que vous ajoutez)
  • import modulename as altname ensembles altname = sys.module['modulename']
  • import packagename.nestedmodule as altname ensembles altname = sys.modules['packagename.nestedmodule']
  • from somemodule import objectname ensembles objectname = sys.modules['somemodule'].objectname
  • from packagename import nestedmodulenameensembles nestedmodulename = sys.modules['packagename.nestedmodulename'](uniquement lorsqu'il n'y avait aucun objet nommé nestedmodulenamedans l' packagenameespace de noms avant cette importation, un nom supplémentaire pour le module imbriqué est ajouté à l'espace de noms du package parent à ce stade)
  • from somemodule import objectname as altname ensembles altname = sys.modules['somemodule'].objectname
  • from packagename import nestedmodulename as altnameensembles altname = sys.modules['packagename.nestedmodulename'](uniquement lorsqu'il n'y avait aucun objet nommé nestedmodulenamedans l' packagenameespace de noms avant cette importation, un nom supplémentaire pour le module imbriqué est ajouté à l'espace de noms du package parent à ce stade)

Vous pouvez tester si le nom auquel l'objet importé était lié existe dans un espace de noms donné:

# 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'])

Cela vous indique seulement que le nom existe (a été lié), pas s'il fait référence à un module ou à un objet spécifique de ce module. Vous pouvez davantage introspecter cet objet ou tester s'il s'agit du même objet que ce qui est disponible dans sys.modules, si vous devez exclure que le nom a été entièrement défini sur autre chose depuis lors.

Martijn Pieters
la source
1
Est-ce le meilleur moyen de rechercher un package requis dans une fonction? Autrement dit, une fonction nécessite un numpypackage - est-ce que l'utilisation import sysà l'intérieur de la fonction est la meilleure pour vérifier qu'elle a été importée? Par «meilleur», j'entends en termes d'impact sur les performances, comme on l' import sysappellera ensuite à chaque appel de la fonction. Merci
Confondé
@Confounded vous pouvez simplement importer des sys en dehors de la fonction si cela vous inquiète. Ce import sysn'est pas du tout cher; sysexiste toujours, il est par défaut déjà chargé. Mais pour un package optionnel: importez simplement le package . Attrapez l' ImportErrorexception si le package n'est pas installé et définissez un indicateur indiquant qu'il est installé lorsque l'importation réussit. Après cela, vous pouvez utiliser l'indicateur pour informer votre utilisation de la dépendance facultative.
Martijn Pieters
@Confounded Le name in sys.modulestest n'est utile que si vous ne souhaitez pas importer .
Martijn Pieters
24

Aux réponses sys.modules acceptées, j'ajouterais une mise en garde pour faire attention au changement de nom des modules lors de l'importation:

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

utilisez sys.modules pour tester si un module a été importé (j'utilise unicodedata comme exemple):

>>> import sys
>>> 'unicodedata' in sys.modules
False
>>> import unicodedata
>>> 'unicodedata' in sys.modules
True
Haresh Shyara
la source
5

sys.modules contient tous les modules utilisés n'importe où dans l'instance actuelle de l'interpréteur et apparaît ainsi s'il est importé dans un autre module Python.

dir() vérifie si le nom a été défini dans l'espace de noms actuel.

La combinaison des 2 est plus sûre que chacune et fonctionne tant que vous n'avez pas défini de copyvous - même.

if ('copy' in sys.modules) and ('copy' in dir()):
HansW
la source
0
if "sys" not in dir():
  print("sys not imported!")
rundekugel
la source
Cela vérifie uniquement si le module a été importé dans l'espace de noms actuel. sysPeut également être n'importe quoi, pas seulement un module.
vaultah