Ich habe eine Zeichenfolge, sagen Sie: abc.def.ghi.jkl.myfile.mymethod
. Wie importiere ich dynamisch mymethod
?
So habe ich es gemacht:
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('.'))
Ich frage mich, ob der Import einzelner Module überhaupt erforderlich ist.
Edit: Ich verwende Python Version 2.6.5.
Ab Python 2.7 können Sie die Funktion importlib.import_module () verwenden. Sie können ein Modul importieren und mit folgendem Code auf ein darin definiertes Objekt zugreifen:
from importlib import import_module
p, m = name.rsplit('.', 1)
mod = import_module(p)
met = getattr(mod, m)
met()
Sie müssen die einzelnen Module nicht importieren. Es reicht aus, das Modul, aus dem Sie einen Namen importieren möchten, zu importieren und das Argument fromlist
anzugeben:
def import_from(module, name):
module = __import__(module, fromlist=[name])
return getattr(module, name)
Rufen Sie für Ihr Beispiel abc.def.ghi.jkl.myfile.mymethod
diese Funktion als auf
import_from("abc.def.ghi.jkl.myfile", "mymethod")
(Beachten Sie, dass Funktionen auf Modulebene in Python als Funktionen bezeichnet werden, nicht als Methoden.)
Für eine solche einfache Aufgabe bietet die Verwendung des Moduls importlib
keinen Vorteil.
Für Python <2.7 kann die eingebaute Methode _ IMPORT_ verwendet werden:
__import__('abc.def.ghi.jkl.myfile.mymethod', fromlist=[''])
Für Python> = 2.7 oder 3.1 wurde die praktische Methode importlib.import_module hinzugefügt. Importiere dein Modul einfach so:
importlib.import_module('abc.def.ghi.jkl.myfile.mymethod')
Update: Aktualisierte Version gemäß Kommentaren (Ich muss zugeben, dass ich die zu importierende Zeichenfolge bis zum Ende nicht gelesen habe. Ich habe die Tatsache übersehen, dass eine Methode eines Moduls importiert werden sollte und kein Modul selbst ):
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")
Es ist nicht klar, was Sie mit Ihrem lokalen Namespace tun möchten. Ich nehme an, Sie möchten nur my_method
als lokale, output = my_method()
eingeben?
# 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()
Während Sie nur my_method
zum lokalen Namespace hinzufügen, laden Sie die Modulkette. Sie können Änderungen anzeigen, indem Sie die Schlüssel von sys.modules
vor und nach dem Import ansehen. Ich hoffe, das ist klarer und genauer als Ihre anderen Antworten.
Der Vollständigkeit halber fügen Sie die gesamte Kette hinzu.
# 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()
Wenn Sie __import__()
verwenden und Ihren Suchpfad nach dem Programmstart geändert haben, müssen Sie möglicherweise __import__(normal args, globals=globals(), locals=locals())
verwenden. Das Warum ist eine komplexe Diskussion.
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
Wie ich dazu neige (wie auch einige andere Bibliotheken, z. B. Pylonen und Einfügen, wenn mir das Gedächtnis gut tut), ist die Trennung des Modulnamens vom Funktions-/Attributnamen, indem ein ':' zwischen ihnen verwendet wird . Siehe folgendes Beispiel:
'abc.def.ghi.jkl.myfile:mymethod'
Dies macht die Funktion import_from(path)
etwas einfacher zu bedienen.
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()
Diese Website hat eine schöne Lösung: load_class . Ich benutze es so:
foo = load_class(package.subpackage.FooClass)()
type(foo) # returns FooClass
Wie gewünscht, hier der Code aus dem Weblink:
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)
Wie wäre es damit :
def import_module(name):
mod = __import__(name)
for s in name.split('.')[1:]:
mod = getattr(mod, s)
return mod