Come verificare se un modulo python è stato importato?


93

Come posso verificare se ho importato un modulo da qualche parte nel codice?

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

Il motivo per cui vorrei controllare se ho già importato un modulo è perché ho un modulo che non voglio importare perché a volte rovina il mio programma.


raise SystemError()Metti semplicemente (o un'altra eccezione a tua scelta) nella parte superiore del modulo che non vuoi importare. Se lo importi effettivamente da qualche parte, il tuo programma lancerà un traceback ed uscirà.
Larsks

In che modo la semplice importazione di un modulo rovina comunque il tuo programma? Non sembra così probabile.
Bill Woodger,

1
@ BillWoodger: forse quel modulo cambia lo stato globale che non vuoi cambiare .
Martijn Pieters

@MartijnPieters Yoiks. E importare suoni così neutri.
Bill Woodger,

Risposte:


126

Verifica il nome del modulo nel sys.modulesdizionario :

import sys

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

Dalla documenazione:

Questo è un dizionario che mappa i nomi dei moduli su moduli che sono già stati caricati.

Nota che importun'istruzione fa due cose:

  1. se il modulo non è mai stato importato prima (== non presente in sys.modules), allora viene caricato e aggiunto a sys.modules.
  2. Associa uno o più nomi nello spazio dei nomi corrente che fanno riferimento all'oggetto del modulo o agli oggetti che sono membri dello spazio dei nomi del modulo.

L'espressione modulename not in sys.modulesverifica se il passaggio 1 è stato eseguito. Il test per il risultato del passaggio 2 richiede la conoscenza di quale importdichiarazione esatta è stata utilizzata poiché impostano nomi diversi per fare riferimento a oggetti diversi:

  • import modulename imposta modulename = sys.modules['modulename']
  • import packagename.nestedmoduleset packagename = sys.modules['packagename'](non importa quanti livelli aggiuntivi aggiungi)
  • import modulename as altname imposta altname = sys.module['modulename']
  • import packagename.nestedmodule as altname imposta altname = sys.modules['packagename.nestedmodule']
  • from somemodule import objectname imposta objectname = sys.modules['somemodule'].objectname
  • from packagename import nestedmodulenameset nestedmodulename = sys.modules['packagename.nestedmodulename'](solo quando non c'era alcun oggetto denominato nestedmodulenamenello packagenamespazio dei nomi prima di questa importazione, un nome aggiuntivo per il modulo nidificato viene aggiunto allo spazio dei nomi del pacchetto padre a questo punto)
  • from somemodule import objectname as altname imposta altname = sys.modules['somemodule'].objectname
  • from packagename import nestedmodulename as altnameset altname = sys.modules['packagename.nestedmodulename'](solo quando non c'era alcun oggetto denominato nestedmodulenamenello packagenamespazio dei nomi prima di questa importazione, un nome aggiuntivo per il modulo nidificato viene aggiunto allo spazio dei nomi del pacchetto padre a questo punto)

Puoi verificare se il nome a cui era associato l'oggetto importato esiste in un determinato spazio dei nomi:

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

Questo ti dice solo che il nome esiste (è stato associato), non se si riferisce a un modulo o oggetto specifico da quel modulo. Potresti esaminare ulteriormente quell'oggetto o verificare se è lo stesso oggetto di quello che è disponibile in sys.modules, se devi escludere che il nome sia stato impostato su qualcos'altro da allora.


1
È questo il modo migliore per verificare la presenza di un pacchetto richiesto all'interno di una funzione? Cioè, diciamo che alcune funzioni richiedono un numpypacchetto: utilizzare import sysall'interno della funzione è il migliore per verificare che sia stato importato? Per "migliore" intendo in termini di impatto sulle prestazioni come import sysverrà quindi chiamato ogni volta che viene chiamata la funzione. Grazie
Confuso

@Confounded puoi semplicemente importare sys al di fuori della funzione se questo ti preoccupa. Non che import syssia in alcun modo costoso; sysesiste sempre, è già caricato per impostazione predefinita. Ma per un pacchetto opzionale: importa semplicemente il pacchetto . Cattura l' ImportErroreccezione se il pacchetto non è installato e imposta un flag che indica che è installato quando l'importazione riesce. Dopodiché puoi usare il flag per informare il tuo utilizzo della dipendenza opzionale.
Martijn Pieters

@Confounded Il name in sys.modulestest è utile solo se non vuoi importare .
Martijn Pieters

26

Alle risposte sys.modules accettate, aggiungerei un avvertimento per fare attenzione a rinominare i moduli durante l'importazione:

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

18

usa sys.modules per verificare se un modulo è stato importato (sto usando unicodedata come esempio):

>>> import sys
>>> 'unicodedata' in sys.modules
False
>>> import unicodedata
>>> 'unicodedata' in sys.modules
True

5

sys.modules contiene tutti i moduli utilizzati ovunque nell'istanza corrente dell'interprete e quindi viene visualizzato se importato in qualsiasi altro modulo Python.

dir() controlla se il nome è stato definito nello spazio dei nomi corrente.

La combinazione dei 2 è più sicura di ciascuna separata e funziona fintanto che non hai definito un copyte stesso.

if ('copy' in sys.modules) and ('copy' in dir()):

0
if "sys" not in dir():
  print("sys not imported!")

Questo controlla solo se il modulo è stato importato nello spazio dei nomi corrente. sysPuò anche essere qualsiasi cosa, non solo un modulo.
vaultah
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.