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
fromlist
argumento: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
importlib
mó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".importlib
en 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_method
como 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_method
al espacio de nombres local, carga la cadena de módulos. Puede ver los cambios observando las claves desys.modules
antes 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_module
ysame_module
está 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 file
fuente
.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 FooClass
Segú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 mod
fuente