Mam ciąg, powiedzieć: abc.def.ghi.jkl.myfile.mymethod
. Jak dynamicznie importować mymethod
?
Oto jak to zrobiłem:
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('.'))
Zastanawiam się, czy w ogóle jest wymagane importowanie poszczególnych modułów.
Edycja: używam Pythona w wersji 2.6.5.
python
dynamic
import
dynamic-import
Lakshman Prasad
źródło
źródło
importlib.import_module()
over__import__()
: docs.python.org/2/library/functions.html#__import__ - dla wersji 2.7+.import_module
+rsplit
= Jedyna prawdziwa droga.Nie musisz importować poszczególnych modułów. Wystarczy zaimportować moduł, z którego chcesz zaimportować nazwę i podać
fromlist
argument:def import_from(module, name): module = __import__(module, fromlist=[name]) return getattr(module, name)
Na przykład
abc.def.ghi.jkl.myfile.mymethod
nazwij tę funkcję jakoimport_from("abc.def.ghi.jkl.myfile", "mymethod")
(Zauważ, że funkcje na poziomie modułu są w Pythonie nazywane funkcjami, a nie metodami).
W przypadku tak prostego zadania nie ma korzyści z korzystania z
importlib
modułu.źródło
myClass = getattr(__import__("module.to.import", fromlist=["myClassName"]), "myClassName")
. Dzięki za pomoc!__import__
podejście działa. Ale spróbuj biechelp(__import__)
. Mówi się: „Ponieważ ta funkcja jest przeznaczona do użytku przez interpreter języka Python, a nie do ogólnego użytku, lepiej jest używać jejimportlib.import_module()
do programowego importu modułu”.importlib
zamiast tego.W przypadku Pythona <2.7 można użyć wbudowanej metody __ import__ :
__import__('abc.def.ghi.jkl.myfile.mymethod', fromlist=[''])
Dla Pythona> = 2.7 lub 3.1 dodano wygodną metodę importlib.import_module . Po prostu zaimportuj swój moduł w następujący sposób:
importlib.import_module('abc.def.ghi.jkl.myfile.mymethod')
Aktualizacja : Zaktualizowana wersja zgodnie z komentarzami ( muszę przyznać, że nie przeczytałem ciągu do zaimportowania do końca i przeoczyłem fakt, że należy importować metodę modułu, a nie sam moduł) :
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")
źródło
__import__()
iimportlib.import_module()
.Nie jest jasne, co próbujesz zrobić z lokalną przestrzenią nazw. Zakładam, że chcesz tylko
my_method
jako lokalny, piszącyoutput = 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()
Chociaż dodajesz tylko
my_method
do lokalnej przestrzeni nazw, ładujesz łańcuch modułów. Możesz przyjrzeć się zmianom, obserwując klawiszesys.modules
przed i po imporcie. Mam nadzieję, że to jest jaśniejsze i dokładniejsze niż twoje inne odpowiedzi.Aby uzyskać kompletność, w ten sposób dodajesz cały łańcuch.
# 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()
I wreszcie, jeśli używasz
__import__()
i zmodyfikowałeś ścieżkę wyszukiwania po uruchomieniu programu, być może będziesz musiał użyć__import__(normal args, globals=globals(), locals=locals())
. Dlaczego jest to złożona dyskusja.źródło
the_module
isame_module
jest źle i produkować różne wyniki. Głosowanie przeciw.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
źródło
.strip()
zachowywał się poprawnie w przypadku, który podałeś. W szczególności, jeśli plik zaczyna się od „py”, te znaki również zostaną usunięte. Na przykład"pyfile.py".strip(".py")
produkuje"file"
, gdzie byłoby preferowane, aby produkować"pyfile"
w tym przypadku.name.replace(".py","")
działa jednak dobrze.Ta strona ma fajne rozwiązanie: load_class . Używam tego w ten sposób:
foo = load_class(package.subpackage.FooClass)() type(foo) # returns FooClass
Zgodnie z żądaniem, oto kod z łącza internetowego:
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)
źródło
Użyj
importlib
(tylko w wersji 2.7+).źródło
from __future__
?__future__
dotyczy funkcji językowych, a nie nowych modułów standardowej biblioteki.__import__
jak w przykładach powyżej. Działa z powrotem do 2.5 i wcześniej bez słów kluczowych.Sposób, w jaki zwykle to robię (a także wiele innych bibliotek, takich jak pylony i wklejanie, jeśli moja pamięć dobrze mi służy) polega na oddzieleniu nazwy modułu od nazwy funkcji / atrybutu za pomocą znaku „:” między nimi . Zobacz poniższy przykład:
'abc.def.ghi.jkl.myfile:mymethod'
To sprawia, że
import_from(path)
poniższa funkcja jest trochę łatwiejsza w użyciu.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()
źródło
Co powiesz na to :
def import_module(name): mod = __import__(name) for s in name.split('.')[1:]: mod = getattr(mod, s) return mod
źródło