动态导入模块,然后实例化具有特定基类的对象来自所述模块

2024-05-29 00:05:46 发布

您现在位置:Python中文网/ 问答频道 /正文

我在写申请书。别胡思乱想GUI:s或任何东西,只是一个简单的旧控制台应用程序。这个应用程序,我们称之为App,需要能够在启动时加载插件。所以,很自然地,我为插件创建了一个类来继承:

class PluginBase(object):
    def on_load(self):
        pass
    def on_unload(self):
        pass
    def do_work(self, data):
        pass

其思想是在启动时,App将遍历当前目录,包括子目录,搜索包含类的模块,这些模块本身就是PluginBase的子类。在

更多代码:

^{pr2}$

search的最后一行之后,我想以某种方式a)查找新加载模块中的所有类,b)检查这些类中是否有一个或多个是PluginBase的子类,并且c)(如果b)实例化这些类并添加到App加载的模块列表中。在

我尝试过issubclass和其他组合,然后是一段时间的紧张{}:ing和大约一个小时惊慌失措的谷歌搜索。我确实找到了一个与我的here相似的方法,我试着复制粘贴,但得到一个错误,说Python不支持按文件名导入,此时我有点失去了注意力,因此,我写了这篇文章。在

我在这里束手无策,感谢大家的帮助。在


Tags: 模块self插件app应用程序objectondef
3条回答

如果您对插件编写器施加一些约束,例如所有插件都必须是包含返回插件实例的load_plugin( app, config)函数的包,那么这将变得更加容易。然后,您所要做的就是尝试导入这些包并运行函数。在

你可以这样做:

for c in candidates:
    modname = os.path.splitext(c)[0]
    try:
        module=__import__(modname)   #<-- You can get the module this way
    except (ImportError,NotImplementedError):
        continue
    for cls in dir(module):          #<-- Loop over all objects in the module's namespace
        cls=getattr(module,cls)
        if (inspect.isclass(cls)                # Make sure it is a class 
            and inspect.getmodule(cls)==module  # Make sure it was defined in module, not just imported
            and issubclass(cls,base)):          # Make sure it is a subclass of base
            # print('found in {f}: {c}'.format(f=module.__name__,c=cls))
            classList.append(cls)

为了测试上面的代码,我不得不修改一下您的代码;下面是完整的脚本。在

^{pr2}$

以下是注册插件的元classier方法:

PluginBase定义为PluginType类型。 PluginType自动注册plugins集中的任何实例(类)。在

插件.py:

plugins=set()
class PluginType(type):
    def __init__(cls, name, bases, attrs):
        super(PluginType, cls).__init__(name, bases, attrs)
        # print(cls, name,cls.__module__)
        plugins.add(cls)

class PluginBase(object):
    __metaclass__=PluginType
    pass

这是用户编写的部分。注意这里没有什么特别的。在

插件/我的插件.py:

^{pr2}$

以下是搜索功能的外观:

测试.py:

import plugin
import os
import imp

def search(plugindir):
    for root, dirs, files in os.walk(plugindir):
        for fname in files:
            modname = os.path.splitext(fname)[0]
            try:
                module=imp.load_source(modname,os.path.join(root,fname))
            except Exception: continue

search('pluginDir')
print(plugin.plugins)

跑步测试.py收益率

set([<class 'myplugin.Foo'>])

相关问题 更多 >

    热门问题