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