Динамический экземпляр Python из строкового имени класса в динамически импортируемом модуле
в python я должен создать экземпляр определенного класса, зная его имя в строке, но этот класс "живет" в динамически импортируемом модуле. Ниже приведен пример:
загрузчика-класс скрипт:
import sys
class loader:
def __init__(self, module_name, class_name): # both args are strings
try:
__import__(module_name)
modul = sys.modules[module_name]
instance = modul.class_name() # obviously this doesn't works, here is my main problem!
except ImportError:
# manage import error
некоторые-динамически загружаемые-модуль скрипта:
class myName:
# etc...
Я использовать этот механизм, чтобы сделать любой динамически-загружаемых-модуль, который будет использоваться погрузчик-класса следующие предварительно определенные модели поведения в Дин-загрузить-модули...
любые идеи оцененный.
6 ответов:
можно использовать getattr
getattr(module, class_name)для доступа к классу. Более полный код:
module = __import__(module_name) class_ = getattr(module, class_name) instance = class_()как уже упоминалось ниже, мы можем использовать importlib
import importlib module = importlib.import_module(module_name) class_ = getattr(module, class_name) instance = class_()
tl; dr
импортируйте модуль с помощью
importlib.import_moduleи загрузите класс, который вам нужен сgetattr:# Standard import import importlib # Load "module.submodule.MyClass" MyClass = getattr(importlib.import_module("module.submodule"), "MyClass") # Instantiate the class (pass arguments to the constructor, if needed) instance = MyClass()объяснениями
вы, вероятно, не хотите использовать
__import__для динамического импорта модуля по имени, так как он не позволяет импортировать подмодули:>>> mod = __import__("os.path") >>> mod.join Traceback (most recent call last): File "<stdin>", line 1, in <module> AttributeError: 'module' object has no attribute 'join'здесь это то, что говорит python doc о
__import__:Примечание: это расширенная функция, которая не нужна в повседневной Программирование на Python, в отличие от importlib.модуль импорта.)(
вместо этого используйте стандарт
importlibмодуль для динамического импорта модуля по имени. Сgetattrзатем вы можете создать экземпляр класса по его имени:import importlib my_module = importlib.import_module("module.submodule") MyClass = getattr(my_module, "MyClass") instance = MyClass()вы также можете написать:
import importlib module_name, class_name = "module.submodule.MyClass".rsplit(".", 1) MyClass = getattr(importlib.import_module(module_name), class_name) instance = MyClass()этот код действителен в python ≥ 2.7 (включая python 3).
использовать
getattrчтобы получить атрибут из имени в строке. Другими словами, получить экземпляр какinstance = getattr(modul, class_name)()
скопировать-вставить фрагмент кода:
import importlib def str_to_class(module_name, class_name) try: module_ = importlib.import_module(module_name) try: class_ = getattr(module_, class_name)() except AttributeError: logging.error('Class does not exist') except ImportError: logging.error('Module does not exist') return class_ or None
Если вы хотите это предложение
from foo.bar import foo2для динамической загрузки, вы должны сделать этоfoo = __import__("foo") bar = getattr(foo,"bar") foo2 = getattr(bar,"foo2") instance = foo2()
Я не мог получить там в моем случае использования из приведенных выше примеров, но Ахмад получил меня ближе всего (спасибо). Для тех, кто читает это в будущем, вот код, который работал для меня.
def get_class(fully_qualified_path, module_name, class_name, *instantiation): """ Returns an instantiated class for the given string descriptors :param fully_qualified_path: The path to the module eg("Utilities.Printer") :param module_name: The module name eg("Printer") :param class_name: The class name eg("ScreenPrinter") :param instantiation: Any fields required to instantiate the class :return: An instance of the class """ p = __import__(fully_qualified_path) m = getattr(p, module_name) c = getattr(m, class_name) instance = c(*instantiation) return instance
Comments