我当前正在编写一个应用程序,允许用户通过“插件”类型的体系结构对其进行扩展。他们可以基于我提供的BaseClass对象编写其他python类,并针对各种应用程序信号加载这些类。在启动应用程序之前,作为插件加载的类的确切数目和名称是未知的,但在启动时仅加载一次。
在研究解决此问题的最佳方法的过程中,我提出了两种常见的解决方案。
选项1-使用imp,pkgutil等自行滚动。
例如,参见此答案或此答案。
选项2-使用插件管理器库
随机选择一对
我的问题是-在其前提是应用程序必须以加载新的插件重新启动-
是有过一些上述方法从灵感任何好处此SO答案和这一个,如:
import inspect
import sys
import my_plugins
def predicate(c):
# filter to classes
return inspect.isclass(c)
def load_plugins():
for name, obj in inspect.getmembers(sys.modules['my_plugins'], predicate):
obj.register_signals()
与上述方法相比,该方法是否有任何缺点?(除了所有的插件必须在同一个文件中)谢谢!
编辑
注释需要更多信息…我唯一想添加的就是插件使用眨眼程序库提供它们所订阅的信号。每个插件可以订阅不同类型的不同信号,因此必须具有自己的特定“注册”方法。
在Python <3.6中,元类方法对于此问题很有用(请参阅@quasoft对于Python
3.6+的回答)。它非常简单,并且可以自动对任何导入的模块起作用。另外,可以很轻松地将复杂的逻辑应用于插件注册。这个需要:
在元类方法的工作原理如下所示:
1)定义了一个自定义PluginMount
元类,其中维护了所有插件的列表
2)Plugin
定义一个将PluginMount
其设置为元类的类
3)例如,当导入一个源自Plugin
-的对象时MyPlugin
,它将触发__init__
该元类上的方法。这将注册插件并执行任何特定于应用程序的逻辑和事件订阅。
或者,如果您将PluginMount.__init__
逻辑放入其中,则在创建派生类PluginMount.__new__
的新实例时将调用该逻辑Plugin
。
class PluginMount(type):
"""
A plugin mount point derived from:
http://martyalchin.com/2008/jan/10/simple-plugin-framework/
Acts as a metaclass which creates anything inheriting from Plugin
"""
def __init__(cls, name, bases, attrs):
"""Called when a Plugin derived class is imported"""
if not hasattr(cls, 'plugins'):
# Called when the metaclass is first instantiated
cls.plugins = []
else:
# Called when a plugin class is imported
cls.register_plugin(cls)
def register_plugin(cls, plugin):
"""Add the plugin to the plugin list and perform any registration logic"""
# create a plugin instance and store it
# optionally you could just store the plugin class and lazily instantiate
instance = plugin()
# save the plugin reference
cls.plugins.append(instance)
# apply plugin logic - in this case connect the plugin to blinker signals
# this must be defined in the derived class
instance.register_signals()
然后是一个基本的插件类,如下所示:
class Plugin(object):
"""A plugin which must provide a register_signals() method"""
__metaclass__ = PluginMount
最后,一个实际的插件类如下所示:
class MyPlugin(Plugin):
def register_signals(self):
print "Class created and registering signals"
def other_plugin_stuff(self):
print "I can do other plugin stuff"
可以从已导入的任何python模块访问插件Plugin
:
for plugin in Plugin.plugins:
plugin.other_plugin_stuff()
查看完整的工作示例
10.2 插件管理器插件介绍 10.2.1 插件管理的必要性 上一节介绍了 vim 用户目录(~/.vim,并推荐设为 $VIMHOME 环境变量)。这在自 己写简单脚本是很方便的,按规范将不同性质与功能的脚本放在不同子目录。但这有个潜 在的问题,源于你不能总是自己造轮子,且不论是否有能力造复杂的轮子。 这世界上多年以来有许多狂热的 vim 爱好者,开发了许多作秀的插件,应该善加选择然 后下载安装
背景 在阅读这个文档前,你应当熟悉Chromium的多进程架构。 概述 插件是浏览器不稳定的主要来源。插件也会在渲染器没有实际运行时,让进程沙箱化。因为进程是第三方编写的,我们无法控制他们对操作系统的访问。解决方案是,让插件在各自独立的进程中运行。 设计细节 进程内插件 Chromium有着在进程内运行插件的能力(对测试来讲非常方便),也可以在进程外运行插件。它们都始于我们的非多进程WebKit嵌
在插件管理,可以查看项目已安装的插件列表,也可以在上方的搜索框中搜索项目已安装的插件,然后更新或卸载它们。 安装插件 点击右上角的“安装插件”按钮后,我们可以浏览所有的插件,这里我们将San CLI插件和San CLI UI插件进行了分类展示,提升搜索效率。 安装 devtools 右上角还提供了安装 devtools 的快捷入口。 注:devtools 是用于调试 san.js 应用的开发工具。
微信文档:https://developers.weixin.qq.com/miniprogram/dev/api-backend/open-api/plugin-management/pluginManager.applyPlugin.html 申请使用插件 $pluginAppId = 'xxxxxxxxx'; $app->plugin->apply($pluginAppId); 删除已添
主要内容:一、Mysql中的Plugin,二、Plugin的架构,三、源码分析,四、总结一、Mysql中的Plugin 在程序设计的发展过程中,插件(Plugin)形式的设计存在的时间很长了,这种源于硬件的插件接口设计,优势在于可以很从容的进行不同场景应用的切换,甚至在运行时也可以通过动态的参数配置来实现整个功能应用场景的快速适配。从Eclipse到Idea等IDE开发工具,到实际的项目开发中,只要开发经验较多的程序员一定会遇到过类似的工程实践。 插件一般是基于一定的插件协议,通过开
我想在我的NetBeans IDE上安装DukeScript插件,但由于某种原因,它没有显示为可用的插件。我可以在NetBeans插件列表中找到它。它甚至有一个符号来表明它是经过认证的,应该可以在IDE中安装。 尝试的解决方案:我尝试从网站上手动下载,我得到了一个带有一堆jar文件和2.nbm文件的zip。我尝试手动添加。nbm文件到插件管理器,我得到以下错误。 在1.0版中请求javax.web
在本章中,我们将研究Joomla中的Plugin Manager 。 它可以帮助您启用和禁用Joomla插件。 这为现有网站添加了独特的功能。 Joomla插件经理 以下是设置或编辑现有Joomla插件的简单步骤 - Step (1) - 单击Joomla管理员中的Extension → Plugin Manager ,如下所示。 Step (2) - 点击Plugin Manager ,将显示现
默认情况下,插件管理器会为您的插件管理动作做出信息反馈。您可以通过添加 --quiet 和 --silent 选项为 install 和 remove 命令控制反馈信息的级别。使用 --quiet 选项屏蔽除错误信息以外的日志输出。使用 --silent 选项屏蔽所有输出。 默认情况下,插件管理器安装插件不会超时。使用 --timeout 选项并添加一个时间来指定安装超时时间: 设定30秒安装超时