pluggy python setuptools entry_points 模式加载插件

已经简单介绍过关于pluggy python 插件包的使用,以下演示下基于python 的setuptools entry_points 模式加载插件
此功能是pluggy 插件注册的一个模式

项目代码结构

  • 结构
├── README.md
├── bootstrap
├── README.md
├── bootstrap
└── app.py
├── poetry.lock
└── pyproject.toml
├── first
├── README.md
├── first
└── plugina
└── __init__.py
├── poetry.lock
└── pyproject.toml
├── second
├── README.md
├── poetry.lock
├── pyproject.toml
├── second
└── pluginb
└── __init__.py
└── tests
└── __init__.py
└── sharespec
    ├── README.md
    ├── poetry.lock
    ├── pyproject.toml
    └── sharespec
        └── __init__.py
  • 简单说明
    为了方便使用基于的pip 的可编辑包模式,将插件的指南独立了独立为了一个包(sharespec),插件项目使用poetry 的本地可编辑依赖(first,second),对于项目的入口也独立了一个python 模块(bootstap)对于以上模块使用了poetry 进行项目管理

代码说明

  • sharespec
    比较简单核心就是接口定义
import pluggy
 
hookspec = pluggy.HookspecMarker("mydemoapp")
hookimpl = pluggy.HookimplMarker("mydemoapp")
 
class MyPlugin:
    @hookspec
    def add(self, x, y):
      """my add hook spec"""
 
    @hookspec
    def sub(self,x,y):
       """my sub hook spec"""
  • first 插件
    pyproject.toml 依赖
[tool.poetry.dependencies]
python = "^3.11"
pluggy = "^1.4.0"
sharespec = { path =  "../sharespec",develop = false}

PluginA 实现

# 引用sharespec模块的定义
from sharespec import hookimpl
 
class PluginA:
    # hookimpl 进行实现处理
    @hookimpl
    def add(self, x, y):
        return x + y
 
    @hookimpl
    def sub(self, x, y):
        return x - y
 # 暴露一个MyPluginA 变量,这样通过entry_points 加载的加载的就是已经实例化的类了
MyPluginA = PluginA()

entry_points 定义

[tool.poetry.plugins."mydemoapp"]
 # plugina 就是注册的插件名称,MyPluginA 使用上边的变量,方便后续使用
"plugina" = "first.plugina:MyPluginA"
  • second 插件
    与first 类似
  • bootstrap
    核心是加载插件意义添加依赖包
    pyproject.toml 依赖
[tool.poetry.dependencies]
python = "^3.11"
sharespec = { path =  "../sharespec",develop = true}
first = { path =  "../first",develop = true}
second = { path =  "../second",develop = true}

app.py (插件的发现以及使用演示)

import  pluggy
from sharespec import MyPlugin
pm = pluggy.PluginManager("mydemoapp")
pm.add_hookspecs(MyPlugin)
pm.load_setuptools_entrypoints("mydemoapp")
result = pm.get_plugin("plugina").add(1, 2)
print(result)
  • 效果


注意以上mydemoapp推荐是一样的(实际是插件指南以及插件管理器的应该一样,entry_points 配置部分的可以选择不同的,但是注意load_setuptools_entrypoints 应该与entry_points plugin 配置的一样),同时对于poetry 依赖更新的命令我没说明,因为都是标准的操作而已(主要是poetry shell,poetry update 命令的使用)

说明

以上是基于pluggy 支持的setuptools entry_points 模式的插件加载,可以方便的实现一个插件化python 系统,而且还比较灵活
对于entry_points 的加载处理使用了importlib.metadata 一个比较常用的模块,完整代码我已经push github 了可以参考

参考资料

https://pluggy.readthedocs.io/en/latest/#registration
https://github.com/rongfengliang/pluggy_plugin_learning

posted on 2024-04-08 00:07  荣锋亮  阅读(62)  评论(0编辑  收藏  举报

导航