Tengo una cadena, por ejemplo: abc.def.ghi.jkl.myfile.mymethod. ¿Cómo importo dinámicamente mymethod?
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 se requiere la importación de módulos individuales.
Editar: estoy usando Python versión 2.6.5.
python
dynamic
import
dynamic-import
Lakshman Prasad
fuente
fuente

importlib.import_module()over__import__(): docs.python.org/2/library/functions.html#__import__ - para 2.7+.import_module+rsplit= El único camino verdadero.No es necesario importar los módulos individuales. Basta con importar el módulo del que desea importar un nombre y proporcionar el
fromlistargumento: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 comoimport_from("abc.def.ghi.jkl.myfile", "mymethod")(Tenga en cuenta que las funciones a nivel de módulo se denominan funciones en Python, no métodos).
Para una tarea tan simple, no hay ninguna ventaja en usar el
importlibmódulo.fuente
myClass = getattr(__import__("module.to.import", fromlist=["myClassName"]), "myClassName"). ¡Gracias por la ayuda!__import__enfoque funciona. Pero intenta correrhelp(__import__). Dice "Debido a que esta función está pensada para que la utilice el intérprete de Python y no para un uso general, es mejor utilizarlaimportlib.import_module()para importar un módulo mediante programación".importliben su lugar.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 conveniente método importlib.import_module . Simplemente importe su módulo así:
importlib.import_module('abc.def.ghi.jkl.myfile.mymethod')Actualización : versión actualizada de acuerdo con los comentarios ( debo admitir que no leí la cadena a importar hasta el final y me perdí el hecho de que se debe importar un método de un módulo 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")fuente
__import__()yimportlib.import_module().No está claro qué está intentando hacer con su espacio de nombres local. Supongo que lo quieres solo
my_methodcomo local, escribiendooutput = 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_methodal espacio de nombres local, carga la cadena de módulos. Puede ver los cambios observando las claves desys.modulesantes y después de la importación. Espero que esto sea más claro y preciso que sus otras respuestas.Para completar, así es como 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á usando
__import__()y ha modificado su ruta de búsqueda después de que se inició el programa, es posible que deba usar__import__(normal args, globals=globals(), locals=locals()). El por qué es una discusión compleja.fuente
the_moduleysame_moduleestá mal y produce resultados diferentes. Votar en contra.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, "classNameImportFromFile") NClass = model() # Class From filefuente
.strip()comporte correctamente en el caso que dijiste. Específicamente, si el archivo comienza con "py", esos caracteres también se eliminarán. Por ejemplo,"pyfile.py".strip(".py")produce"file", donde sería preferible que produjera"pyfile"en este caso.name.replace(".py","")funciona bien, sin embargo.Este sitio web tiene una buena solución: load_class . Lo uso así:
foo = load_class(package.subpackage.FooClass)() type(foo) # returns FooClassSegún lo solicitado, aquí está el código del enlace web:
import importlib def load_class(full_class_string): """ dynamically load a class from a string """ class_data = full_class_string.split(".") module_path = ".".join(class_data[:-1]) class_str = class_data[-1] module = importlib.import_module(module_path) # Finally, we retrieve the Class return getattr(module, class_str)fuente
Utilice
importlib(solo 2.7+).fuente
from __future__algo?__future__es para funciones de idioma, no para nuevos módulos stdlib.__import__como en los ejemplos anteriores. Funciona de nuevo a 2.5 y, sin palabras clave, antes.La forma en que tiendo a esto (así como a otras bibliotecas, como pilones y pegar, si mi memoria no me falla) es separar el nombre del módulo del nombre de la función / atributo usando un ':' entre ellos . Vea el siguiente ejemplo:
'abc.def.ghi.jkl.myfile:mymethod'Esto hace que la
import_from(path)función siguiente sea 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()fuente
Qué tal esto :
def import_module(name): mod = __import__(name) for s in name.split('.')[1:]: mod = getattr(mod, s) return modfuente