我正在研究一个项目,该项目从另一个模块动态收集类,并根据找到的类创建新类。例如,如果源模块具有“ AdaptiveFilter”类,则将创建一个名为“ AdaptiveFilterNode”的新类,其中包含“ AdaptiveFilter”实例。我一直将这些生成的类添加到动态创建的模块(module_from_spec()
)中,并分别创建了MetaPathFinder
和Loader
来扩展import
系统。导入动态模块(例如, import nodes.auto_gen
或from nodes.auto_gen import AdaptiveFilterNode
,但在尝试直接导入类时失败,例如import nodes.auto_gen.AdaptiveFilterNode
。我需要能够直接导入一个类,因为生成的类需要是可腌制的,这需要直接导入。我相信问题出在我制作的Finder中:
class MyNodeFinder(MetaPathFinder):
def find_spec(self, fullname, path=None, target=None):
if fullname == 'nodes.auto_gen':
auto_gen_spec = = ModuleSpec('nodes.auto_gen',
MyLoader())
return auto_gen_spec
return None
根据我对导入系统的有限了解,查找程序或模块规范中没有任何内容可以告诉导入系统nodes.auto_gen
模块中包含的类,直到模块已加载。如何创建具有动态类的动态模块的标准导入系统的查找器/加载器?
编辑:完整示例,模块“ dynamic_creator”:
dynamic_creator / __ init __。py
from importlib.machinery import ModuleSpec
from importlib.util import module_from_spec
import sys
from importlib.abc import MetaPathFinder
from importlib.abc import Loader
__version__ = '0.0.0'
class _MyWrapperClass():
wrapped_func = None
def __init__(self):
super().__init__()
def __call__(self, *args, **kwargs):
return self.wrapped_func(*args, **kwargs)
class MyFinder(MetaPathFinder):
def find_spec(self, fullname, path=None, target=None):
if fullname == 'dynamic_creator.auto_gen':
auto_node_spec = ModuleSpec('dynamic_creator.auto_gen',
MyLoader())
return auto_node_spec
return None
class MyLoader(Loader):
def create_module(self, spec):
return module_from_spec(ModuleSpec('dynamic_creator.auto_gen', None))
def exec_module(self, module):
def create_type(func):
t = type(func.__name__, (_MyWrapperClass, ), {})
t.wrapped_func = func
# Wait, you can do this?
t.__module__ = 'dynamic_creator.auto_gen'
return t
funcs_to_wrap = [
sum,
abs,
pow
]
for func in funcs_to_wrap:
setattr(module, func.__name__, create_type(func))
my_finder = MyFinder()
sys.meta_path.append(my_finder)
测试脚本:
import dynamic_creator.auto_gen # Works
from dynamic_creator.auto_gen import abs # Works
import dynamic_creator.auto_gen.pow as my_pow # Fails
编辑:报告的错误如下:
No module named 'dynamic_creator.auto_gen.pow'; 'dynamic_creator.auto_gen' is not a package