动态导入模块中类的字符串名称的Python动态实例化

时间:2011-01-27 19:49:58

标签: python

在python中,我必须实例化某个类,知道它在字符串中的名称,但这个类“存在”一个动态导入的模块中。一个例子如下:

loader-class脚本:

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中遵循某些预定义的行为由loader-class使用...

任何想法都表示赞赏。

9 个答案:

答案 0 :(得分:198)

您可以使用getattr

getattr(module, class_name)

访问该课程。更完整的代码:

module = __import__(module_name)
class_ = getattr(module, class_name)
instance = class_()

如上所述below,我们可能会使用importlib

import importlib
module = importlib.import_module(module_name)
class_ = getattr(module, class_name)
instance = class_()

答案 1 :(得分:102)

TL;博士

使用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'

Here是python doc关于__import__所说的内容:

  

注意:这是日常不需要的高级功能   Python编程,与importlib.import_module()不同。

而是使用标准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)中有效。

答案 2 :(得分:11)

使用getattr从字符串中的名称获取属性。换句话说,将实例作为

instance = getattr(modul, class_name)()

答案 3 :(得分: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

答案 4 :(得分:5)

如果您希望动态加载此句from foo.bar import foo2,则应执行此操作

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

instance = foo2()

答案 5 :(得分:2)

在上面的例子中,我无法完成我的用例,但艾哈迈德让我最接近(谢谢)。对于那些将来阅读本文的人来说,这里的代码对我有用。

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

答案 6 :(得分:2)

如果你想从字符串中导入一个类和方法,你应该这样做:

dynamic_import 
│   my_class.py
│      
└───subfolder
│   │   my_subfolder_module.py
│   │
<块引用>

my_subfolder_module.py

 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"

答案 7 :(得分:1)

一个人可以简单地使用pydoc.locate函数。

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

答案 8 :(得分:0)

使用以下代码片段:

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)