美文网首页
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