Pythondynamic实例化从dynamic导入模块中的类的string名称
在python中,我必须实例化某个类,知道它的名字在一个string中,但是这个类“生活”在一个dynamic导入的模块中。 一个例子如下:
加载器类脚本:
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
一些dynamic加载的模块脚本:
class myName: # etc...
我使用这种安排,使得在dyn-loaded-modules中按照某些预定义的行为,由loader-class使用任何dynamic加载的模块。
任何想法都表示赞赏。
你可以使用getattr
getattr(module, class_name)
去上课。 更完整的代码:
module = __import__(module_name) class_ = getattr(module, class_name) instance = class_()
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__
按名称dynamic导入模块,因为它不允许导入子模块:
>>> 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__
所说的内容:
注意:与importlib.import_module()不同,这是日常Python编程中不需要的高级函数。
相反,使用标准的importlib
模块按名称dynamic导入模块。 使用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)中是有效的。
使用getattr
从string中的名称获取属性。 换句话说,获取实例
instance = getattr(modul, class_name)()
复制粘贴片段:
def str_to_class(module_name, class_name) 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
如果你想from foo.bar import foo2
这个句子来dynamic加载,你应该这样做
foo = __import__("foo") bar = getattr(foo,"bar") foo2 = getattr(bar,"foo2") instance = foo2()
从上面的例子中,我不能完全达到目的,但艾哈迈德让我最接近(谢谢)。 对于那些将来阅读这些内容的人来说,这里是为我工作的代码。
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