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

loader类脚本:

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-module脚本:

class myName:
  # etc...

我使用这种安排使加载器类使用任何动态加载模块,遵循动态加载模块中的某些预定义行为…


当前回答

如果你想从foo中得到这句话。Bar import foo2来动态加载,你应该这样做

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

instance = foo2()

其他回答

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

instance = getattr(modul, class_name)()

复制粘贴代码片段:

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

博士tl;

使用importlib导入根模块。使用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文档对__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)中有效。

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

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"

如果你想从foo中得到这句话。Bar import foo2来动态加载,你应该这样做

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

instance = foo2()