módulo de importação da variável string

183

Estou trabalhando em uma documentação (pessoal) para a biblioteca aninhada matplotlib (MPL), que difere da própria MPL fornecida, pelos pacotes de submodulos interessados. Estou escrevendo um script Python, que espero automatize a geração de documentos a partir de versões futuras do MPL.
Selecionei submódulos / pacotes interessados ​​e quero listar suas principais classes a partir das quais gerarei a lista e a processarei compydoc

O problema é que não consigo encontrar uma maneira de instruir o Python para carregar o submódulo da string. Aqui está um exemplo do que eu tentei:

import matplotlib.text as text
x = dir(text)

.

i = __import__('matplotlib.text')
y = dir(i)

.

j = __import__('matplotlib')
z = dir(j)

E aqui está uma comparação de três maneiras das listas acima através do pprint:

insira a descrição da imagem aqui

Eu não entendo o que é carregado no yobjeto - é base matplotlibmais alguma outra coisa, mas falta informações que eu queria e são as principais classes do matplotlib.textpacote. É a parte superior azul na captura de tela ( xlista)

Por favor, não sugira Sphinx como uma abordagem diferente.

teta
fonte
Você pode explicar por que precisa usar __import__(str)em vez do importstatemetn padrão ?
Thesamet
É porque eu vou processar listas de quais itens são submódulos MPL e obter os seus métodos de caminhos
teta
9
@ thesamet - vamos lá - existem inúmeras idéias em que você deseja essa funcionalidade. Quando você tem uma configuração textual de bibliotecas, pode carregá-las pelo nome, o que não funcionaria muito com a importinstrução Aqui está um exemplo de uso: djangosnippets.org/snippets/3048
Tomasz Gandor

Respostas:

279

A __import__função pode ser um pouco difícil de entender.

Se você mudar

i = __import__('matplotlib.text')

para

i = __import__('matplotlib.text', fromlist=[''])

então iirá se referir a matplotlib.text.

No Python 2.7 e Python 3.1 ou posterior, você pode usar importlib:

import importlib

i = importlib.import_module("matplotlib.text")

Algumas notas

  • Se você estiver tentando importar algo de uma subpasta, por exemplo ./feature/email.py, o código será semelhante aimportlib.import_module("feature.email")

  • Você não pode importar nada se não houver __init__.pyna pasta com o arquivo que você está tentando importar

mzjn
fonte
3
importlibdeve estar disponível no pypi para <python2.7
Jeffrey Jose
50
Para quem vem do Google para cá. Note-se que se você está tentando importar algo de uma sub-pasta (por exemplo, ./feature/email.py) o código será semelhanteimportlib.import_module("feature.email")
Seanny123
11
Finalmente, lembre-se de que você não pode importar nada se não houver __init__.pyna pasta com o arquivo que você está tentando importar.
Seanny123
3
@mzjn É para import moduleNameonde moduleName é string. Que tal from moduleName import *?
Nam G VU
2
Resposta Só encontrei a minha pergunta aqui no caso de alguém precisa dele stackoverflow.com/a/31306598/248616
Nam G VU
68

importlib.import_moduleé o que você está procurando. Retorna o módulo importado. (Disponível apenas para Python> = 2.7 ou 3.x):

import importlib

mymodule = importlib.import_module('matplotlib.text')

Depois disso, você pode acessar qualquer coisa no módulo como mymodule.myclass, etc.

gecco
fonte
Uma alternativa é imp.load_source(..)usar o impmódulo, conforme sugerido nesta resposta stackoverflow.com/questions/67631/…
Evgeni Sergeev
5
@ gecco É para import moduleNameonde moduleName é string. Que tal from moduleName import *?
Nam G VU
6

passei algum tempo tentando importar módulos de uma lista, e esse é o segmento que me levou a maior parte do caminho até lá - mas não compreendi o uso de ___import____ -

aqui está como importar um módulo de uma string e obter o mesmo comportamento que basta importar. E tente / exceto o caso de erro também. :)

  pipmodules = ['pycurl', 'ansible', 'bad_module_no_beer']
  for module in pipmodules:
      try:
          # because we want to import using a variable, do it this way
          module_obj = __import__(module)
          # create a global object containging our module
          globals()[module] = module_obj
      except ImportError:
          sys.stderr.write("ERROR: missing python module: " + module + "\n")
          sys.exit(1)

e sim, para python 2.7> você tem outras opções - mas para 2.6 <, isso funciona.

afiado
fonte
1

Eu desenvolvi estas 3 funções úteis:

def loadModule(moduleName):
    module = None
    try:
        import sys
        del sys.modules[moduleName]
    except BaseException as err:
        pass
    try:
        import importlib
        module = importlib.import_module(moduleName)
    except BaseException as err:
        serr = str(err)
        print("Error to load the module '" + moduleName + "': " + serr)
    return module

def reloadModule(moduleName):
    module = loadModule(moduleName)
    moduleName, modulePath = str(module).replace("' from '", "||").replace("<module '", '').replace("'>", '').split("||")
    if (modulePath.endswith(".pyc")):
        import os
        os.remove(modulePath)
        module = loadModule(moduleName)
    return module

def getInstance(moduleName, param1, param2, param3):
    module = reloadModule(moduleName)
    instance = eval("module." + moduleName + "(param1, param2, param3)")
    return instance

E toda vez que quero recarregar uma nova instância, basta chamar getInstance () assim:

myInstance = getInstance("MyModule", myParam1, myParam2, myParam3)

Finalmente, posso chamar todas as funções dentro da nova instância:

myInstance.aFunction()

A única especificidade aqui é personalizar a lista de parâmetros (param1, param2, param3) da sua instância.

prossblad
fonte
1

Além de usar o importlibone, também é possível usar o execmétodo para importar um módulo de uma variável de string.

Aqui estou mostrando um exemplo de importação do combinationsmétodo do itertoolspacote usando o execmétodo:

MODULES = [
    ['itertools','combinations'],
]

for ITEM in MODULES:
    import_str = "from {0} import {1}".format(ITEM[0],', '.join(str(i) for i in ITEM[1:]))
    exec(import_str)

ar = list(combinations([1, 2, 3, 4], 2))
for elements in ar:
    print(elements)

Resultado:

(1, 2)
(1, 3)
(1, 4)
(2, 3)
(2, 4)
(3, 4)
arsho
fonte