theta
Estoy trabajando en una documentación (personal) para la biblioteca anidada matplotlib (MPL), que difiere de la propia MPL proporcionada, por paquetes de submódulos interesados. Estoy escribiendo un script de Python que espero automatice la generación de documentos de futuras versiones de MPL.
Seleccioné submódulos/paquetes interesados y quiero enumerar sus clases principales a partir de las cuales generaré una lista y la procesaré con pydoc
.
El problema es que no puedo encontrar una manera de indicarle a Python que cargue un submódulo de una cadena. Aquí hay un ejemplo de lo que probé:
import matplotlib.text as text
x = dir(text)
i = __import__('matplotlib.text')
y = dir(i)
j = __import__('matplotlib')
z = dir(j)
Y aquí hay una comparación de 3 vías de las listas anteriores a través de pprint:
No entiendo lo que está cargado y
objeto – es base matplotlib
además de algo más, pero le falta la información que quería y que son las clases principales de matplotlib.text
paquete. Es la parte superior de color azul en la captura de pantalla (x
lista).
mzjn
El __import__
La función puede ser un poco difícil de entender.
si cambias
i = __import__('matplotlib.text')
a
i = __import__('matplotlib.text', fromlist=[''])
entonces i
se referirá a matplotlib.text
.
En Python 3.1 o posterior, puede usar importlib
:
import importlib
i = importlib.import_module("matplotlib.text")
Algunas notas
-
Si está tratando de importar algo desde una subcarpeta, por ejemplo
./feature/email.py
el código se verá comoimportlib.import_module("feature.email")
-
Antes de Python 3.3, no podía importar nada si no había
__init__.py
en la carpeta con el archivo que intentaba importar (vea las advertencias antes de decidir si desea mantener el archivo para compatibilidad con versiones anteriores, por ejemplo, conpytest
).
-
importlib
debería estar disponible en pypi para– Jeffrey José
19 de agosto de 2012 a las 12:12
-
Para cualquiera que venga aquí desde Google. Cabe señalar que si está tratando de importar algo de una subcarpeta (por ejemplo,
./feature/email.py
) el código se verá comoimportlib.import_module("feature.email")
– Seanny123
6 de diciembre de 2013 a las 7:13
-
Por último, recuerda también que no puedes importar nada si no hay
__init__.py
en la carpeta con el archivo que está intentando importar.– Seanny123
6 de diciembre de 2013 a las 7:31
-
@mzjn Esto es para
import moduleName
donde moduleName es una cadena. Qué tal sifrom moduleName import *
?– Nam G VU
30 de mayo de 2017 a las 6:47
-
Acabo de encontrar la respuesta a mi pregunta aquí en caso de que alguien la necesite stackoverflow.com/a/31306598/248616
– Nam G VU
30 de mayo de 2017 a las 7:54
gecco
importlib.import_module
es lo que buscas Devuelve el módulo importado.
import importlib
# equiv. of your `import matplotlib.text as text`
text = importlib.import_module('matplotlib.text')
A partir de entonces, puede acceder a cualquier cosa en el módulo como text.myclass
, text.myfunction
etc.
-
Una alternativa es
imp.load_source(..)
utilizando elimp
módulo como se sugiere en esta respuesta stackoverflow.com/questions/67631/…–Evgeni Sergeev
8 de junio de 2014 a las 6:30
-
@gecco Esto es para
import moduleName
donde moduleName es una cadena. Qué tal sifrom moduleName import *
?– Nam G VU
30 de mayo de 2017 a las 6:57
-
¿Alguien descifra la pregunta de @NamGVU?
– Piedra del artillero
22 de marzo de 2022 a las 23:05
pasé algún tiempo tratando de importar módulos de una lista, y este es el hilo que me llevó la mayor parte del camino, pero no entendí el uso de ___import____ –
así que aquí se explica cómo importar un módulo desde una cadena y obtener el mismo comportamiento que solo importar. Y prueba/excepto el caso de error, también. 🙂
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)
y sí, para python 2.7> tiene otras opciones, pero para 2.6
Aparte de usar el importlib
uno también puede usar exec
método para importar un módulo desde una variable de cadena.
Aquí estoy mostrando un ejemplo de importar el combinations
método de itertools
paquete usando el exec
mé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)
Producción:
(1, 2)
(1, 3)
(1, 4)
(2, 3)
(2, 4)
(3, 4)
También puedes usar exec
función incorporada que ejecuta cualquier cadena como un código de Python.
In [1]: module="pandas"
...: function = 'DataFrame'
...: alias="DF"
In [2]: exec(f"from {module} import {function} as {alias}")
In [3]: DF
Out[3]: pandas.core.frame.DataFrame
Para mí, esta fue la forma más legible de resolver mi problema.
serge stroobandt
Módulo de instalación automática e importación desde la lista
El siguiente script funciona bien tanto con submódulos como con pseudosubmódulos.
# PyPI imports
import pkg_resources, subprocess, sys
modules = {'lxml.etree', 'pandas', 'screeninfo'}
required = {m.split('.')[0] for m in modules}
installed = {pkg.key for pkg in pkg_resources.working_set}
missing = required - installed
if missing:
subprocess.check_call([sys.executable, '-m', 'pip', 'install', '--upgrade', 'pip'])
subprocess.check_call([sys.executable, '-m', 'pip', 'install', *missing])
for module in set.union(required, modules):
globals()[module] = __import__(module)
Pruebas:
print(pandas.__version__)
print(lxml.etree.LXML_VERSION)
Prosblad
Desarrollé estas 3 funciones útiles:
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
Y cada vez que quiero recargar una nueva instancia, solo tengo que llamar a getInstance() de esta manera:
myInstance = getInstance("MyModule", myParam1, myParam2, myParam3)
Finalmente puedo llamar a todas las funciones dentro de la nueva Instancia:
myInstance.aFunction()
La única especificidad aquí es personalizar la lista de parámetros (param1, param2, param3) de su instancia.
¿Puedes explicar por qué necesitas usar
__import__(str)
en lugar del estándarimport
declaración?– el mismo
3 de enero de 2012 a las 21:53
Es porque procesaré listas cuyos elementos son submódulos MPL y obtendré las rutas de sus métodos.
– theta
03/01/2012 a las 22:00
@thesamet – vamos – hay un sinfín de ideas en las que le gustaría esta funcionalidad. Cuando tiene una configuración textual de bibliotecas, puede cargarlas por nombre, lo que no funcionaría del todo con el
import
declaración. He aquí un ejemplo de uso: djangosnippets.org/snippets/3048– Tomasz Gandor
12 de mayo de 2014 a las 4:55