[英]Dynamic instantiation from string name of a class in dynamically imported module?
在 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...
我使用这种安排来使任何动态加载的模块由加载器类按照动态加载模块中的某些预定义行为使用...
使用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__
:
注意:与 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(包括 python 3)中有效。
使用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
可以简单地使用pydoc.locate
函数。
from pydoc import locate
my_class = locate("module.submodule.myclass")
instance = my_class()
如果你想让这句话from foo.bar import foo2
被动态加载,你应该这样做
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
如果你想从字符串导入一个类和方法,你应该这样做:
dynamic_import
│ my_class.py
│
└───subfolder
│ │ my_subfolder_module.py
│ │
my_subfolder_module.py
class MySubfolderClass():
def test_method(self):
print ("Hello World")
主文件
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"
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)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.