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插件架构
随机推荐
- Java Web 开发填坑记- 如何正确的下载 Eclipse
一直以来,做 Java web 开发都是用 eclipse , 可是到 eclipse 官网一看,我的天 http://www.eclipse.org/downloads/eclipse-packag ...
- ionic插件安装与卸载
使用下面的命令查询.安装.卸载插件: $ ionic plugin list //列出所有已安装插件 $ ionic plugin remove 插件名 //先根据上面的list列出插件,然后根据插件 ...
- 4种更快更简单实现Python数据可视化的方法
数据可视化是数据分析或机器学习项目中十分重要的一环.通常,你需要在项目初期进行探索性的数据分析(EDA),从而对数据有一定的了解,而且创建可视化确实可以使分析的任务更清晰.更容易理解,特别是对于大规模 ...
- MySQL锁系列之锁的种类和概念
转自:http://keithlan.github.io/2017/06/05/innodb_locks_1/ 锁是MySQL里面最难理解的知识,但是又无处不在. 一开始接触锁的时候,感觉被各种锁类型 ...
- sql server复制表数据到另外一个表 的存储过程
) Drop Procedure GenerateData go CREATE PROCEDURE GenerateData @tablename sysname AS begin ) ) ) dec ...
- python web编程CGI
CGI(通用网关接口),CGI 是Web 服务器运行时外部程序的规范,按CGI 编写的程序可以扩展服务器功能. CGI 应用程序能与浏览器进行交互,还可通过数据库API 与数据库服务器等外部数据源进行 ...
- CVE-2013-2551
目录 小白的CVE-2013-2551 分析 & 利用 0xFF 前言 0x00 环境和工具 0x01 分析POC POC 调试 0x02 利用 构造R3任意内存读写 劫持eip 利用利用 0 ...
- python闭包,看不懂请揍我
什么是闭包? 闭包就是一个个内嵌函数+内嵌函数里面引用了外部变量+返回这个内嵌函数(一般是这样) 为什么使用闭包? 有点类似与函数模板?.. 举一个实际的例子: class people: name ...
- linux禁止非法用户试探登录
当我们的linux主机一旦暴露在互联网上,就会遭受到来自网络上的一些非法用户的骚扰.如弱口令扫描,试探性登录:这些行为对linux主机构成一定的威胁.那怎样防范此类的攻击了,这里写了一个脚本,功能就是 ...
- 封装Ajax框架!(前言篇)
Ajax技术就是利用javascript和xml实现异步交互的功能. 首先先来介绍一下Ajax相关知识点,如果这些你都会的话,请直接跳转到封装ajax框架!(代码篇) 一.Ajax对象的创建 1.创建 ...