Yapsy实例化错误的类当扩展IPlugin时

1 投票
1 回答
677 浏览
提问于 2025-04-18 12:09

我有一个文件结构,它使用Yapsy实现了一个非常简单的插件架构。

Plugins/BasePlugin.py

from yapsy.IPlugin import IPlugin

class BasePlugin(IPlugin):
    def process(self):
        # Do some stuff common to all plugins
        pass

Plugins/TestPlugin.py

from Plugins.BasePlugin import BasePlugin

class TestPlugin(BasePlugin):
    def process(self, info):
        super(TestPlugin, self).process()
        # Do stuff
        return "done"

test.py

from yapsy.PluginManager import PluginManager
from Plugins.BasePlugin import BasePlugin
import logging

logging.basicConfig(level=logging.DEBUG)
# See note 1
manager = PluginManager()   # Does not work
manager = PluginManager(categories_filter={'BasePlugin': BasePlugin}) # Works

def init_plugins():
    # Load the plugins from the plugin directory.
    manager.setPluginPlaces(["Plugins"])
    manager.collectPlugins()

    # Loop round the plugins and print their names.
    for plugin in manager.getAllPlugins():
        manager.activatePluginByName(plugin.name, "BasePlugin")
        print "Plugin path: {}".format(plugin.path)
        print "Plugin obj:  {}".format(plugin.plugin_object)

        result = plugin.plugin_object.process(info)

还有一个正确的 .yapsy-plugin 信息文件,用于 TestPlugin。

如果没有过滤器(在注释1中提到),Yapsy会尝试实例化一个 BasePlugin,而不是我的 TestPlugin,尽管插件的名字是 "TestPlugin"。举个例子:

Plugin path: /home/user/python/Plugins/TestPlugin
Plugin obj:  <Plugins.BasePlugin.BasePlugin object at 0x7f159af22050>

如果我加上过滤器,那么插件就能正确加载,我的 TestPlugin 类会被实例化并使用。

DEBUG:yapsy:Activating plugin: BasePlugin.test
Plugin path: /home/david/python/Plugins/TestPlugin
Plugin obj:  <yapsy_loaded_plugin_test_0.TestPlugin object at 0x7f4dad7d4050>

我在继承方面是不是做错了什么,还是说这就是 Yapsy 的工作方式?我看不出为什么它会尝试使用 BasePlugin,而不是 TestPlugin,尽管找到了正确的文件。

我需要实现类别来扩展IPlugin并提供我自己的基类吗?

1 个回答

3

你遇到了yapsy的一个已知问题,这个问题和它如何在文件中检测插件以及对插件进行分类有关。

这个问题在yapsy的文档的故障排除部分有详细说明,链接在这里:https://yapsy.readthedocs.org/en/latest/Advices.html#plugin-class-detection-caveat

因为这些话是我自己写的,所以我就直接复制粘贴过来了。如果有什么不明白的地方,随时可以问我。


每个模块中只能定义一个插件。这意味着你不能有两个插件描述文件指向同一个模块。

由于“通过继承进行分类”的系统,你不能直接在主插件文件中导入的子类,而是应该导入它所在的模块,并让你的插件类继承自,就像下面的例子一样。

下面的代码是行不通的(类会被识别为插件的实现,而不是):

from myapp.plugintypes import MyBasePluginClass

class MyPlugin(MyBasePluginClass):
    pass

相反,你应该这样做:

import myapp.plugintypes as plugintypes

class MyPlugin(plugintypes.MyBasePluginClass):
    pass

撰写回答