美文网首页
Python插件实现1

Python插件实现1

作者: 波波2 | 来源:发表于2020-03-30 22:46 被阅读0次

前言

本文是前一文章的继续,主要是开始着手Python脚本代码的实现。预期来说,本文将完成以下功能:

  1. 加载2个插件;
  2. 实现一个简化的插件上下文;
  3. 实现一个简化的插件加载框架;
  4. 实现一个主程序;
  5. 实现扩一个扩展演示;
  6. 实现一个服务注册演示;
  7. 实现一个订阅演示;
    代码仓库:https://gitee.com/imlaji/PythonPluginFW

实现逻辑

预期两个插件中,一个负责APP启动,另一个负责扩展实现。APP扩展点名是一个系统默认扩展点,名称为PL::APP,扩展点接口定义为:

class APP:
    def name(self):
        return ""
    def run(self, argv):
        return ""

主程序

主程序负责驱动插件框架加载插件,然后在插件上下文中查询PL::APP扩展,使用指定名称的APP扩展进行应用启动执行。

import context
import framework

import sys

def main():
    plcontext = context.context()
    pl = framework.framework()
    pl.load(plcontext, "./plugins")

    apps = plcontext.find_extension("PL::APP")
    app = None
    
    for a in apps:
        if a.name() == "MyApp":
            app = a
            break
    if app == None:
        print("PL::APP not match!")
    else:
        app.run(sys.argv)

main()

插件框架

插件框架负责动态加载目录中的插件,为了简单,本例暂时使用静态加载。后续版本进行修改完善。


import plugins.plugina.plugin as plugina
import plugins.pluginb.plugin as pluginb

class framework:
    def load(self, context, path):
        plugina.init(context)
        pluginb.init(context)

        for ex in plugina.config["extensions"]:
            context.add_extension(ex['name'], ex['impl'])

        for service in plugina.config["services"]:
            context.add_service(service['name'], service['define'])

        #for subscribe in plugina.config["subscribes"]:
        #    context.add_subscribe(subscribe['name'], subscribe['define'])
        
        for ex in pluginb.config["extensions"]:
            context.add_extension(ex['name'], ex['impl'])

        #for service in pluginb.config["services"]:
        #    context.add_service(service['name'], service['define'])

        for subscribe in pluginb.config["subscribes"]:
            context.add_subscribe(subscribe['name'], subscribe['define'])

        print("Hello!")

插件上下文

插件上下文主要记录了插件框架的所有数据信息,是插件框架的核心数据中心。


class context:
    plugins = []
    extensions = {}
    services = {}
    subscribes = {}

    def add_plugin(self, plugin):
        self.plugins.append(plugin)
    def get_plugins(self):
        return self.plugins
    
    def add_extension(self, extype, ext):
        if not extype in self.extensions:
            self.extensions[extype] = []
        self.extensions[extype].append(ext)
    def find_extension(self, extype):
        if extype in self.extensions:
            return self.extensions[extype]
        else:
            return []
    
    def add_service(self, name, service):
        self.services[name] = service
    def find_service(self, name):
        if name in self.services:
            return self.services[name]
        else:
            return None

    def add_subscribe(self, name, callback):
        if not name in self.subscribes:
            self.subscribes[name] = []
        self.subscribes[name].append(callback)
    def fire(self, name, value):
        if name in self.subscribes:
            for callback in self.subscribes[name]:
                callback(value)

APP插件

APP插件实现了框架默认的PL::APP扩展点。并且定义了新的扩展点,也定义了一个服务,同时出发了一个订阅事件。



context = None

def init(context_):
    global context
    context = context_


class MyApp:
    def name(self):
        return "MyApp"

    def run(self, argv):
        context.fire("Event1", {"id", 20})

        exts = context.find_extension("PL::Test1")
        for ext in exts:
            ext.test()
            
        print("Hello in MyAPP!!")

class MyTest:
    def test(self):
        print("Hello Test!")

def HelloServiceFun(a, b):
    print("HelloService:", a+b)



config = {
    "extensions" : [
        {
            "name": "PL::APP",
            "impl": MyApp()
        }
    ],
    "extensions_def" : [
        {
            "name": "PL::Test1",
            "define": MyTest
        }
    ],
    "services" : [
        {
            "name": "HelloService",
            "define": HelloServiceFun
        }
    ]
}

插件b

插件b完全就是为了配合APP插件,完成相关功能的交互。实现了APP插件扩展的插桩点,并且使用了APP插件的服务,同时订阅了一个事件消息。


context = None
def init(context_):
    global context
    context = context_

class MyApp:
    def name(self):
        return "MyApp"

    def run(self, argv):
        print("Hello in MyAPP!!")

class MyTest:
    def test(self):
        print("Hello Test222!")

def MyEventFun(val):
    service = context.find_service("HelloService")
    if (service):
        service(30, 40)
    print("MyEventFun:", val)

config = {
    "extensions" : [
        {
            "name": "PL::Test1",
            "impl": MyTest()
        }
    ],
    "subscribes" : [
        {
            "name": "Event1",
            "define": MyEventFun
        }
    ]
}

总结

当我们理清我们想要什么,就会发现实现一个插件框架是非常快的。本文主要演示了插件框架的基本概念实现,后续文章将继续针对本插件框架进行结构优化,动态加载插件,定义框架本身事件,服务添加属性描述等,并逐步开始添加UI的交互。

相关文章

网友评论

      本文标题:Python插件实现1

      本文链接:https://www.haomeiwen.com/subject/zfabuhtx.html