从动态导入模块中根据字符串名称动态实例化类?
在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...
我使用这种方式来让任何动态加载的模块按照预先定义好的行为被加载器类使用...
10 个回答
22
复制粘贴代码片段:
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
176
简要说明
使用 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文档对 __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)都是有效的。
368