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']
  • 插件是冷插拔的
  • 插件不是懒加载

优化方向

  • 热插拔
  • 懒加载
本文转自罗兵博客园博客,原文链接:http://www.cnblogs.com/hhh5460/p/6681363.html ,如需转载请自行联系原作者
相关文章
|
21天前
|
机器学习/深度学习 测试技术 数据处理
KAN专家混合模型在高性能时间序列预测中的应用:RMoK模型架构探析与Python代码实验
Kolmogorov-Arnold网络(KAN)作为一种多层感知器(MLP)的替代方案,为深度学习领域带来新可能。尽管初期测试显示KAN在时间序列预测中的表现不佳,近期提出的可逆KAN混合模型(RMoK)显著提升了其性能。RMoK结合了Wav-KAN、JacobiKAN和TaylorKAN等多种专家层,通过门控网络动态选择最适合的专家层,从而灵活应对各种时间序列模式。实验结果显示,RMoK在多个数据集上表现出色,尤其是在长期预测任务中。未来研究将进一步探索RMoK在不同领域的应用潜力及其与其他先进技术的结合。
61 4
|
2月前
|
监控 安全 中间件
Python Django 后端架构开发: 中间件架构设计
Python Django 后端架构开发: 中间件架构设计
25 1
|
2月前
|
Python
Sublime Text Python 代码提示插件 Anaconda
Sublime Text Python 代码提示插件 Anaconda
63 1
|
2月前
|
Kubernetes Python 容器
[python]使用diagrams绘制架构图
[python]使用diagrams绘制架构图
|
3月前
|
Kubernetes Cloud Native 微服务
探索云原生技术:Kubernetes在微服务架构中的应用Python编程之旅:从基础到进阶
【7月更文挑战第31天】随着云计算技术的迅猛发展,云原生概念应运而生,它代表了一种构建和运行应用程序的全新方式。本文将通过实际代码示例,深入探讨Kubernetes这一云原生关键技术如何在微服务架构中发挥其强大的作用。我们将从容器化开始,逐步过渡到Kubernetes集群的搭建与管理,最后展示如何部署和管理一个微服务应用。
46 2
|
3月前
|
Web App开发 JavaScript 前端开发
Chrome插件实现问题之最新的 Chrome 浏览器架构有什么新的改变吗
Chrome插件实现问题之最新的 Chrome 浏览器架构有什么新的改变吗
|
3月前
|
JSON Go C++
开发与运维C++问题之在iLogtail新架构中在C++主程序中新增插件的概念如何解决
开发与运维C++问题之在iLogtail新架构中在C++主程序中新增插件的概念如何解决
36 1
|
2月前
|
监控 Ubuntu 网络协议
如何在 Ubuntu 12.10 上使用 Python 创建 Nagios 插件
如何在 Ubuntu 12.10 上使用 Python 创建 Nagios 插件
7 0
|
3月前
|
监控 前端开发 JavaScript
构建高效实时应用:Python WebSocket在前后端分离架构中的实践
【7月更文挑战第18天】WebSocket助力实时Web应用,通过一次握手建立持久连接,解决HTTP实时性问题。Python中可用Flask-SocketIO创建WebSocket服务器,前端JavaScript使用Socket.IO库连接。确保安全可采用HTTPS、认证及跨域限制。示例代码展示如何实现双向实时通信。
91 4
下一篇
无影云桌面