¿Cómo comprobar si se ha importado un módulo de Python?

91

¿Cómo verifico si importé un módulo en algún lugar del código?

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

La razón por la que me gustaría comprobar si ya importé un módulo es porque tengo un módulo que no quiero importar porque a veces estropea mi programa.

Yuval
fuente
Simplemente coloque raise SystemError()(u otra excepción de su elección) en la parte superior del módulo que no desea importar. Si no realmente importa en algún lugar, su programa arrojará un rastreo y salida.
larsks
De todos modos, ¿cómo es que la importación de un módulo estropea su programa? No parece tan probable.
Bill Woodger
1
@BillWoodger: tal vez ese módulo cambie el estado global que no desea cambiar .
Martijn Pieters
@MartijnPieters Yoiks. Y la importación suena tan neutral.
Bill Woodger
¿Posible duplicado de cómo probar si se ha importado un módulo de Python?
Shadowtalker

Respuestas:

122

Prueba el nombre del módulo en el sys.modulesdiccionario :

import sys

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

De la documentación:

Este es un diccionario que asigna nombres de módulos a módulos que ya se han cargado.

Tenga en cuenta que una importdeclaración hace dos cosas:

  1. si el módulo nunca se ha importado antes (== no está presente en sys.modules), entonces se carga y se agrega sys.modules.
  2. Enlaza 1 o más nombres en el espacio de nombres actual que hacen referencia al objeto del módulo o a objetos que son miembros del espacio de nombres del módulo.

La expresión modulename not in sys.modulescomprueba si se ha realizado el paso 1. La prueba del resultado del paso 2 requiere saber qué importdeclaración exacta se usó, ya que establecen diferentes nombres para hacer referencia a diferentes objetos:

  • import modulename conjuntos modulename = sys.modules['modulename']
  • import packagename.nestedmoduleconjuntos packagename = sys.modules['packagename'](no importa cuántos niveles adicionales agregue)
  • import modulename as altname conjuntos altname = sys.module['modulename']
  • import packagename.nestedmodule as altname conjuntos altname = sys.modules['packagename.nestedmodule']
  • from somemodule import objectname conjuntos objectname = sys.modules['somemodule'].objectname
  • from packagename import nestedmodulenameconjuntos nestedmodulename = sys.modules['packagename.nestedmodulename'](solo cuando no había ningún objeto nombrado nestedmodulenameen el packagenameespacio de nombres antes de esta importación, se agrega un nombre adicional para el módulo anidado al espacio de nombres del paquete principal en este punto)
  • from somemodule import objectname as altname conjuntos altname = sys.modules['somemodule'].objectname
  • from packagename import nestedmodulename as altnameconjuntos altname = sys.modules['packagename.nestedmodulename'](solo cuando no había ningún objeto nombrado nestedmodulenameen el packagenameespacio de nombres antes de esta importación, se agrega un nombre adicional para el módulo anidado al espacio de nombres del paquete principal en este punto)

Puede probar si el nombre al que estaba vinculado el objeto importado existe en un espacio de nombres determinado:

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

Esto solo le indica que el nombre existe (se ha vinculado), no si se refiere a un módulo u objeto específico de ese módulo. Puede realizar una introspección adicional de ese objeto o probar si es el mismo objeto que el que está disponible en sys.modules, si necesita descartar que el nombre se haya establecido en algo completamente diferente desde entonces.

Martijn Pieters
fuente
1
¿Es esta la mejor manera de verificar un paquete requerido dentro de una función? Es decir, digamos que alguna función requiere un numpypaquete: ¿usar import sysdentro de la función es lo mejor para verificar que se ha importado? Por "mejor" me refiero en términos del impacto en el rendimiento, como import sysse llamará cada vez que se llame a la función. Gracias
Confundido
@ Confundido, simplemente puede importar sys fuera de la función si eso le preocupa. No import syses que sea ​​caro de ninguna manera; syssiempre existe, por defecto ya está cargado. Pero para un paquete opcional: simplemente importe el paquete . Detecte la ImportErrorexcepción si el paquete no está instalado y establezca una marca que indique que está instalado cuando la importación se realice correctamente. Después de eso, puede usar la bandera para informar su uso de la dependencia opcional.
Martijn Pieters
@Confounded La name in sys.modulesprueba solo es útil si no desea importar .
Martijn Pieters
24

A las respuestas de sys.modules aceptadas, agregaría una advertencia para tener cuidado al cambiar el nombre de los módulos en la importación:

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

use sys.modules para probar si se ha importado un módulo (estoy usando unicodedata como ejemplo):

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

sys.modules contiene todos los módulos utilizados en cualquier lugar de la instancia actual del intérprete y, por lo tanto, aparece si se importa en cualquier otro módulo de Python.

dir() comprueba si el nombre se definió en el espacio de nombres actual.

La combinación de los 2 es más segura que cada uno por separado y funciona siempre que no lo hayas definido copytú mismo.

if ('copy' in sys.modules) and ('copy' in dir()):
HansW
fuente
0
if "sys" not in dir():
  print("sys not imported!")
rundekugel
fuente
Eso solo verifica si el módulo se importó en el espacio de nombres actual. También syspuede ser cualquier cosa, no solo un módulo.
vaultah