python 优雅地实现插件架构
近日,决定用 python 实现插件架构,于是上 stackoverflow 逛了一下,在这里发现一段代码,非常喜欢。
提醒各位大侠注意,我对这段代码作了一点小小的改动:原 PLUGINS 是 list 对象,改动后 PLUGINS 是 dict 对象。
代码先贴出来,以飨观众:
''' 插件架构 '''
# 平台
class TextProcessor(object):
PLUGINS = {}
def process(self, text, plugins=()):
if plugins is ():
for plugin_name in self.PLUGINS.keys():
text = self.PLUGINS[plugin_name]().process(text)
else:
for plugin_name in plugins:
text = self.PLUGINS[plugin_name]().process(text)
return text
@classmethod
def plugin_register(cls, plugin_name):
def wrapper(plugin):
cls.PLUGINS.update({plugin_name:plugin})
return plugin
return wrapper
# 插件
@TextProcessor.plugin_register('plugin1')
class CleanMarkdownBolds(object):
def process(self, text):
return text.replace('**', '')
# 测试
processor = TextProcessor()
print(processor.PLUGINS) # {’plugin1': <class '__main__.CleanMarkdownBolds'>}
processed = processor.process(text="**foo bar**", plugins=('plugin1', ))
processed = processor.process(text="**foo bar**")
这段代码运行良好!但是它是单文件,不适合实际使用。
在实际项目中,上面的三个注释下面的部分一定是拆开的,其中插件一般都约定俗成地放到 plugins 子目录下。
为了实现这个想法,走了很多弯路,花了两天时间!这期间查阅了__metaclass__原理, __subclass__()函数, package的组织方式等等。最后真的灵光一闪,成功实现!
项目结构:
├─ myproject
├─ run.py
├─ app
├─ __init__.py
├─ main.py
├─ platform.py
├─ plugins
├─ __init__.py
├─ plugin1.py
├─ plugin2.py
完整代码
# mpyproject/app/platform.py
class TextProcessor(object):
PLUGINS = {}
def process(self, text, plugins=()):
if plugins is ():
for plugin_name in self.PLUGINS.keys():
text = self.PLUGINS[plugin_name]().process(text)
else:
for plugin_name in plugins:
text = self.PLUGINS[plugin_name]().process(text)
return text
@classmethod
def plugin_register(cls, plugin_name):
def wrapper(plugin):
cls.PLUGINS.update({plugin_name:plugin})
return plugin
return wrapper
# mpyproject/app/plugins/plugin1.py
from ..platform import TextProcessor
@TextProcessor.plugin_register('plugin1')
class CleanMarkdownBolds(object):
def process(self, text):
return text.replace('**', '')
# mpyproject/app/plugins/plugin2.py
# 第二个插件!
from ..platform import TextProcessor
@TextProcessor.plugin_register('plugin2')
class CleanMarkdownItalic(object):
def process(self, text):
return text.replace('--', '')
# mpyproject/app/main.py
from .platform import TextProcessor
def test():
processor = TextProcessor()
print(processor.PLUGINS) # {’plugin1': <class '__main__.CleanMarkdownBolds'>}
processed = processor.process(text="**foo bar**", plugins=('plugin1', ))
processed = processor.process(text="--foo bar--")
# mpyproject/app/__init__.py
from .plugins import *
# mpyproject/app/plugins/__init__.py
__all__ = ['plugin1', 'plugin2']
# mpyproject/run.py
from app.main import test
test()
说明:
- 优雅地实现插件架构,
app/__init__.py与app/plugins/__init__.py两个文件起了相互呼应的作用 - 在 app 目录下,除了
app/__init__.py,不需要在别的任何地方显式地导入插件:from .plugins import *或from .plugins import plugin1 - 若想添加插件 plugin3.py,可将其复制到 plugins 目录下,然后修改
app/plugins/__init__.py文件为__all__ = ['plugin1', 'plugin2', 'plugin3'] - 插件是冷插拔的
- 插件不是懒加载
优化方向
- 热插拔
- 懒加载
python 优雅地实现插件架构的更多相关文章
- [1] 插件架构(PLUG-IN)
网上的一种比较好对插件的定义是:插件(Plug-in,又称addin.add-in.addon或add-on,又译外挂)也称为扩展,是一种遵循一定规范的应用程序接口编写出来的程序,主要是用来扩展软件功 ...
- 在C#程序中实现插件架构
阅读提示:这篇文章将讲述如何利用C#奇妙的特性,实现插件架构,用插件(plug-ins)机制建立可扩展的解决方案. 在.NET框架下的C#语言,和其他.NET语言一样提供了很多强大的特性和机制.其中一 ...
- 【Chromium中文文档】插件架构
插件架构 转载请注明出处:https://ahangchen.gitbooks.io/chromium_doc_zh/content/zh//General_Architecture/Plugin_A ...
- Python:开发Sublime插件,方便PHP开发
Python:开发Sublime插件,方便PHP开发 背景 最近在学习PHP,开发环境选择了Sublime2,开发过程发现执行PHP程序非常不方便,需要自己在浏览器中输入路径以进行调试,这点不如Dre ...
- C++插件架构浅谈与初步实现
一.插件架构初步介绍 想到写本博客,也没想到更好的名字,目前就先命这个名吧.说到插件架构,或许大部分IT从业者都听过或者某些牛人也自己实现过稳定高效的插件框架.目前有很多软件以及库都是基于插件架构,例 ...
- vim python自动补全插件:pydiction
vim python自动补全插件:pydiction 可以实现下面python代码的自动补全: 1.简单python关键词补全 2.python 函数补全带括号 3.python 模块补全 4.pyt ...
- Mac Sublime Text 3 配置Python环境及安装插件
一.下载安装Sublime Text 3 官网下载地址:http://www.sublimetext.com/3 二.配置Python开发环境 1.点击右下角,选择python 2.添加编译环境pyt ...
- DELPHI开发LINUX插件架构的程序
DELPHI开发LINUX插件架构的程序 DELPHI可以开发LINUX配置型插件架构的程序,并且这一套插件架构,同样适用于MSWINDOWS和MAC. 配置插件: 根据配置,动态加载插件:
- 咏南跨平台中间件支持LINUX和WINDOWS插件架构
咏南跨平台中间件支持LINUX和WINDOWS插件架构
随机推荐
- Android--根据子控件的大小自动换行的ViewGroup
1.自定义ViewGroup /** * Created by Administrator on 2016/2/26. * * --------自动换行的ViewGroup----------- */ ...
- JSP源码、改写Servlet为JSP、查看转译成为Servlet的文件、JSP字符编码设置
概述 在Servlet中编写HTML太麻烦了,应该使用JSP.JSP中可以直接编写HTML,使用指示.声明.脚本(scriptlet)等元素来堆砌各种功能,但JSP最后还是会被容器转译为Servlet ...
- Expo大作战(二十七)--expo sdk api之Util(expo自带工具类),tackSnapshotAsync,Svg,SQLite
简要:本系列文章讲会对expo进行全面的介绍,本人从2017年6月份接触expo以来,对expo的研究断断续续,一路走来将近10个月,废话不多说,接下来你看到内容,讲全部来与官网 我猜去全部机翻+个人 ...
- 多媒体指令(AVX加速数组求和)
#include <stdio.h> #include <intrin.h> #include <iostream> #include <ctime> ...
- SQLSERVER群集故障转移笔记
SQLSERVER群集故障转移笔记 出自<SQLSERVER2012实施与管理实战指南> SQLSERVER故障转移 P41 事实上,从sqlserver2000到sqlserver200 ...
- soapui 调用wsdl 步骤以及出现的问题
创建soap project 添加wsdl 地址(或者导入wsdl(后缀可以是xml或者wsdl)文件) 添加request 自动生成请求代码 参数放在in0 中 <soapenv:Envelo ...
- 【史上最全】申请配置阿里云服务器,并部署IIS和开发环境,项目上线经验
最近一年在实验室做web后端开发,涉及到一些和服务器搭建及部署上线项目的相关经验,写个帖子和小伙伴们分享,一同进步! 首先谈一下,为什么越来越多中小型公司/实验室,部署项目的趋势都是在云服务器而不是普 ...
- 'javac' 不是内部或外部命令,也不是可运行的程序
今天在命令行中运行javac命令时发现 但是运行java命令却可以 查找jdk的安装路径发现,安装目录里面同时有jdk的文件夹和jre的文件夹 查看了jdk的目录发现jdk目录中也有一个jre文件夹 ...
- Alpha冲刺报告(5/12)(麻瓜制造者)
今日已完成 明日计划 部分api示意图 燃尽图 scrum会议照片 今日已完成 邓弘立: 完成部分首页逻辑功能 符天愉: 写代码写着写着想起来昨天的登录接口有个非常zz的逻辑错误,今天修改完后应该没有 ...
- 团队作业——Alpha冲刺 6/12
团队作业--Alpha冲刺 冲刺任务安排 杨光海天 今日任务:编辑界面完成标题栏的开发,以及与已经完成gallery开发的同学,商讨我负责的界面中,图片滑动的具体措施. 明日任务:除了图像识别内容嵌入 ...