Como verificar se um módulo python foi importado?

93

Como posso verificar se importei um módulo em algum lugar do código?

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

Gostaria de verificar se já importei um módulo porque tenho um módulo que não quero importar porque às vezes bagunça meu programa.

Yuval
fonte
Basta colocar raise SystemError()(ou outra exceção de sua escolha) no topo do módulo que você não deseja importar. Se você não realmente importá-lo em algum lugar, seu programa irá lançar um rastreamento e sair.
larsks
Como apenas importar um módulo bagunça seu programa? Não parece tão provável.
Bill Woodger
1
@BillWoodger: talvez aquele módulo mude o estado global que você não quer mudar .
Martijn Pieters
@MartijnPieters Yoiks. E a importação soa tão neutra.
Bill Woodger
Possível duplicata de como testar se um módulo Python foi importado?
shadowtalker de

Respostas:

126

Teste o nome do módulo no sys.modulesdicionário :

import sys

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

Da documentação:

Este é um dicionário que mapeia nomes de módulos para módulos que já foram carregados.

Observe que uma importdeclaração faz duas coisas:

  1. se o módulo nunca foi importado antes (== não está presente em sys.modules), ele é carregado e adicionado sys.modules.
  2. Vincule 1 ou mais nomes no namespace atual que fazem referência ao objeto do módulo ou a objetos que são membros do namespace do módulo.

A expressão modulename not in sys.modulestesta se a etapa 1 ocorreu. O teste para o resultado da etapa 2 requer saber qual importinstrução exata foi usada, pois eles definem nomes diferentes para fazer referência a objetos diferentes:

  • import modulename conjuntos modulename = sys.modules['modulename']
  • import packagename.nestedmoduleconjuntos packagename = sys.modules['packagename'](não importa quantos níveis adicionais você adicionar)
  • 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'](somente quando não havia nenhum objeto nomeado nestedmodulenameno packagenamenamespace antes desta importação, um nome adicional para o módulo aninhado é adicionado ao namespace do pacote pai neste ponto)
  • from somemodule import objectname as altname conjuntos altname = sys.modules['somemodule'].objectname
  • from packagename import nestedmodulename as altnameconjuntos altname = sys.modules['packagename.nestedmodulename'](somente quando não havia nenhum objeto nomeado nestedmodulenameno packagenamenamespace antes desta importação, um nome adicional para o módulo aninhado é adicionado ao namespace do pacote pai neste ponto)

Você pode testar se o nome ao qual o objeto importado foi associado existe em um determinado namespace:

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

Isso apenas informa se o nome existe (foi vinculado), não se ele se refere a um módulo ou objeto específico desse módulo. Você pode examinar mais profundamente esse objeto ou testar se é o mesmo objeto que está disponível sys.modules, se precisar descartar que o nome foi definido como algo totalmente diferente desde então.

Martijn Pieters
fonte
1
Esta é a melhor maneira de verificar se há um pacote necessário dentro de uma função? Ou seja, digamos que alguma função requeira numpypacote - usar import sysdentro da função é o melhor para verificar se ela foi importada? Por "melhor", quero dizer, em termos de impacto no desempenho, como import sysserá então chamado cada vez que a função for chamada. Obrigado
Confundido
@Confounded, você pode simplesmente importar sistemas fora da função se isso o preocupa. Não que import sysseja de forma alguma caro; syssempre existe, por padrão já está carregado. Mas para um pacote opcional: basta importar o pacote . Capture a ImportErrorexceção se o pacote não estiver instalado e defina um sinalizador indicando que ele está instalado quando a importação for bem-sucedida. Depois disso, você pode usar o sinalizador para informar seu uso da dependência opcional.
Martijn Pieters
@Confounded O name in sys.modulesteste só é útil se você não quiser importar .
Martijn Pieters
26

Para as respostas sys.modules aceitas, eu adicionaria uma advertência para ter cuidado ao renomear os módulos na importação:

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

use sys.modules para testar se um módulo foi importado (estou usando unicodedata como exemplo):

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

sys.modules contém todos os módulos usados ​​em qualquer lugar na instância atual do interpretador e, portanto, é exibido se importado em qualquer outro módulo Python.

dir() verifica se o nome foi definido no namespace atual.

A combinação dos 2 é mais segura do que cada um separadamente e funciona desde que você não tenha definido um copy.

if ('copy' in sys.modules) and ('copy' in dir()):
HansW
fonte
0
if "sys" not in dir():
  print("sys not imported!")
rundekugel
fonte
Isso apenas verifica se o módulo foi importado no namespace atual. Também syspode ser qualquer coisa, não apenas um módulo.
vaultah