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


179

파이썬에서는 문자열에서 이름을 알고 특정 클래스를 인스턴스화해야하지만이 클래스는 동적으로 가져온 모듈에 '살아 있습니다'. 예는 다음과 같습니다.

로더 클래스 스크립트 :

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...

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

답변:


251

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

3
module = __import__(module, fromlist=[name])오직 나를 위해 일했다.
umpirsky

16
위에서 언급 한 가져 오기 방법 Sven에 문제가있는 사람은 importlib.import_module 대신 다음 방법을 사용하여 코드가 더 잘 작동한다는 것을 알았습니다 . 다음과 같이 사용할 수 있습니다 : module = importlib.import_module (module_name)
jpennell

@jpennell 당신은 대답으로 게시해야합니다.obj.__module__
Anentropic

importlib.import_module필요한 경우 .py 파일을 pyc에로드하고 전체 module.name.pathing.to.get.to. 클래스를 처리합니다. __import__장고 환경에서이 두 가지 중 하나를 수행하지 않습니다 (외부에서 테스트되지 않음)
James

122

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'

파이썬 문서가 말한 내용은 다음과 같습니다__import__ .

참고 : 이것은 importlib.import_module ()과 달리 일상적인 Python 프로그래밍에 필요하지 않은 고급 기능입니다.

대신 표준 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 (파이썬 3 포함)에서 유효합니다.


1
어쩌면 나는 당신의 대답을 이해하지 못하지만 하위 모듈을 가져 오기 위해 import를 사용했습니다 : __import __ ( "module."+ submodule_name_string)
Javier Novoa C.

다음 코드는 AttributeError를 mod = __import__("os.path"); mod.join발생시킵니다. 다음은 mod = importlib.import_module("os.path"); mod.join
그렇지

아시다시피, 당신 말이 맞지만 os.path.join 메소드를 얻기 위해 다음을 수행했습니다 : getattr (sys.modules [ "os.path"], "join")
Javier Novoa C.

하아! 그리고 그것을 사용할 때 ' 가져 오기 '는 불필요한 XD
Javier Novoa C.

2
응답으로 표시된 옵션이 (서브 모듈을 사용하여) 나에게 효과가 없었지만이 대답은 그렇지 않습니다. 모듈을 동적으로로드하기위한보다 일반적인 솔루션이기 때문에 대답해야한다고 생각합니다.
rkachach

14

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

instance = getattr(modul, class_name)()

10

복사하여 붙여 넣기 스 니펫 :

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

5

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

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

instance = foo2()

4

간단히 pydoc.locate함수 를 사용할 수 있습니다 .

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

2

위의 예제에서 유스 케이스에 도달하지 못했지만 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
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.