python - texto - Importe dinámicamente un método en un archivo, desde una cadena
guardar una lista en un archivo python (8)
Tengo una cadena, por ejemplo: abc.def.ghi.jkl.myfile.mymethod
. ¿Cómo importo mymethod
forma dinámica?
Así es como lo hice:
def get_method_from_file(full_path):
if len(full_path) == 1:
return map(__import__,[full_path[0]])[0]
return getattr(get_method_from_file(full_path[:-1]),full_path[-1])
if __name__==''__main__'':
print get_method_from_file(''abc.def.ghi.jkl.myfile.mymethod''.split(''.''))
Me pregunto si es necesario importar los módulos individuales.
Editar: estoy usando la versión 2.6.5 de Python.
Desde Python 2.7 puede usar la función importlib.import_module() . Puede importar un módulo y acceder a un objeto definido dentro de él con el siguiente código:
from importlib import import_module
p, m = name.rsplit(''.'', 1)
mod = import_module(p)
met = getattr(mod, m)
met()
Este sitio web tiene una buena solución: load_class . Lo uso así:
foo = load_class(package.subpackage.FooClass)()
type(foo) # returns FooClass
La manera en que tiendo a esto (así como a varias otras bibliotecas, como pilones y pegar, si mi memoria me sirve correctamente) es separar el nombre del módulo del nombre de función / atributo usando un '':'' entre ellos . Vea el siguiente ejemplo:
''abc.def.ghi.jkl.myfile:mymethod''
Esto hace que la función import_from(path)
un poco más fácil de usar.
def import_from(path):
"""
Import an attribute, function or class from a module.
:attr path: A path descriptor in the form of ''pkg.module.submodule:attribute''
:type path: str
"""
path_parts = path.split('':'')
if len(path_parts) < 2:
raise ImportError("path must be in the form of pkg.module.submodule:attribute")
module = __import__(path_parts[0], fromlist=path_parts[1])
return getattr(module, path_parts[1])
if __name__==''__main__'':
func = import_from(''a.b.c.d.myfile:mymethod'')
func()
No está claro lo que intenta hacer con su espacio de nombres local. Supongo que quieres solo my_method
como local, escribiendo output = my_method()
?
# This is equivalent to "from a.b.myfile import my_method"
the_module = importlib.import_module("a.b.myfile")
same_module = __import__("a.b.myfile")
# import_module() and __input__() only return modules
my_method = getattr(the_module, "my_method")
# or, more concisely,
my_method = getattr(__import__("a.b.myfile"), "my_method")
output = my_method()
Si bien solo agrega my_method
al espacio de nombres local, carga la cadena de módulos. Puede ver los cambios observando las claves de sys.modules
antes y después de la importación. Espero que esto sea más claro y más preciso que tus otras respuestas.
Para completar, así es como se agrega toda la cadena.
# This is equivalent to "import a.b.myfile"
a = __import__("a.b.myfile")
also_a = importlib.import_module("a.b.myfile")
output = a.b.myfile.my_method()
# This is equivalent to "from a.b import myfile"
myfile = __import__("a.b.myfile", fromlist="a.b")
also_myfile = importlib.import_module("a.b.myfile", "a.b")
output = myfile.my_method()
Y, finalmente, si está utilizando __import__()
y ha modificado su ruta de búsqueda después de que se inició el programa, es posible que necesite usar __import__(normal args, globals=globals(), locals=locals())
. El por qué es una discusión compleja.
No necesita importar los módulos individuales. Es suficiente importar el módulo del que desea importar un nombre y proporcionar el argumento de la lista:
def import_from(module, name):
module = __import__(module, fromlist=[name])
return getattr(module, name)
Para su ejemplo abc.def.ghi.jkl.myfile.mymethod
, llame a esta función como
import_from("abc.def.ghi.jkl.myfile", "mymethod")
(Tenga en cuenta que las funciones de nivel de módulo se llaman funciones en Python, no en los métodos).
Para una tarea tan simple, no hay ninguna ventaja al usar el módulo importlib
.
Para Python <2.7, se puede usar el método incorporado __ import__ :
__import__(''abc.def.ghi.jkl.myfile.mymethod'', fromlist=[''''])
Para Python> = 2.7 o 3.1, se ha agregado el método conveniente importlib.import_module . Solo importa tu módulo de esta manera:
importlib.import_module(''abc.def.ghi.jkl.myfile.mymethod'')
Actualización : versión actualizada según los comentarios ( debo admitir que no leí la cadena que se importará hasta el final y me olvidé del hecho de que un método de un módulo debería importarse y no un módulo en sí) :
Python <2.7:
mymethod = getattr(__import__("abc.def.ghi.jkl.myfile", fromlist=["mymethod"]))
Python> = 2.7:
mymethod = getattr(importlib.import_module("abc.def.ghi.jkl.myfile"), "mymethod")
Use importlib
(solo 2.7+).
from importlib import import_module
name = "file.py".strip(''.py'')
# if Path like : "path/python/file.py"
# use name.replaces("/",".")
imp = import_module(name)
# get Class From File.py
model = getattr(imp, "naemClassImportFromFile")
NClass = model() # Class From file