source

동적으로 Import된 모듈의 클래스 문자열 이름에서 동적 인스턴스화?

gigabyte 2023. 1. 12. 22:06
반응형

동적으로 Import된 모듈의 클래스 문자열 이름에서 동적 인스턴스화?

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

some-dynamically-loaded-interval 스크립트:

class myName:
  # etc...

이 배열을 사용하여 동적으로 로드된 모듈을 로더 클래스에서 사용할 수 있도록 합니다. dyn-loaded-modules의 사전 정의된 동작에 따라...

getatr을 사용할 수 있습니다.

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_()

dr;dr

루트 모듈을 Import 합니다.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__서브모듈을 Import할 수 없으므로 모듈 이름을 사용하여 동적으로 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__:

주의: 이것은 importlib.import_module()과 달리 일상적인 Python 프로그래밍에서는 필요하지 않은 고급 함수입니다.

대신 표준 모듈을 사용하여 모듈을 이름으로 동적으로 Import합니다.그러면 이름을 사용하여 클래스를 인스턴스화할 수 있습니다.

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 2.7(python 3 포함)에서 유효합니다.

복사 붙여넣기 스니펫:

import importlib
def str_to_class(module_name, class_name):
    """Return a class instance from a string reference"""
    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

사용하다getattr문자열 이름에서 속성을 가져옵니다.즉, 인스턴스를 다음과 같이 가져옵니다.

instance = getattr(modul, class_name)()

를 간단하게 사용할 수 있습니다.pydoc.locate기능.

from pydoc import locate
my_class = locate("module.submodule.myclass")
instance = my_class()

이 문장을 원한다면from foo.bar import foo2동적으로 로드하려면 이 작업을 수행해야 합니다.

foo = __import__("foo")
bar = getattr(foo,"bar")
foo2 = getattr(bar,"foo2")

instance = foo2()

문자열에서 클래스 및 메서드를 Import하려면 다음 작업을 수행해야 합니다.

dynamic_import 
│   my_class.py
│      
└───subfolder
│   │   my_subfolder_module.py
│   │

my_sysloger_syslogs.화이

 class MySubfolderClass():
        def test_method(self):
            print ("Hello World")

main.py

import importlib 
  
module = importlib.import_module('subfolder.my_subfolder_module')
class_ = getattr(module, "MySubfolderClass")
method_instance = getattr(class_(),"test_method")
method_instance()
#it will output the result of the test method, which is "Hello World"

위의 예로는 제 사용 사례에 거의 도달할 수 없었습니다만, Ahmad가 가장 가까운 곳을 찾아 주었습니다(감사합니다).앞으로 이 글을 읽으실 분들을 위해, 여기 제게 효과가 있었던 코드가 있습니다.

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

다음 코드 조각 사용:

def to_class(path:str):
    try:
        from pydoc import locate
        class_instance = locate(path)
    except ImportError:
        print('Module does not exist')
    return class_instance or None

사용방법:

당신의 클래스 이름이 인 경우MyClass에 배치되어 있습니다.my_app.models.MyClass그 후, 다음과 같이 합니다.

path = "my_app.models.MyClass"
my_class = to_class(path)

언급URL : https://stackoverflow.com/questions/4821104/dynamic-instantiation-from-string-name-of-a-class-in-dynamically-imported-module

반응형