扩展动态模块的导入系统

时间:2020-05-28 18:09:44

标签: python python-import

我正在研究一个项目,该项目从另一个模块动态收集类,并根据找到的类创建新类。例如,如果源模块具有“ AdaptiveFilter”类,则将创建一个名为“ AdaptiveFilterNode”的新类,其中包含“ AdaptiveFilter”实例。我一直将这些生成的类添加到动态创建的模块(module_from_spec())中,并分别创建了MetaPathFinderLoader来扩展import系统。导入动态模块(例如, import nodes.auto_genfrom 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

0 个答案:

没有答案