Динамический экземпляр 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...


Я использовать этот механизм, чтобы сделать любой динамически-загружаемых-модуль, который будет использоваться погрузчик-класса следующие предварительно определенные модели поведения в Дин-загрузить-модули...



любые идеи оцененный.

184   6  

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

    Ничего не найдено.