找回密码
 立即注册
首页 业界区 安全 用pluggy实现动态载入模块

用pluggy实现动态载入模块

管水芸 2025-6-1 20:52:15
用pluggy实现动态载入模块

pluggy是pytest用的一个插件系统, 通过pluggy我们可以实现动载入插件模块功能.

  • 用 pluggy.HookspecMarker 声明一个spec, 确定一个插件需要实现哪些方法.
这里我们定义了一个str2str的实现规范, 它需要一个process的函数用于处理字符串.
  1. import pluggy
  2. import pathlib
  3. import importlib
  4. hookspec = pluggy.HookspecMarker("str2str")
  5. class Str2StrSpec:
  6.     @hookspec
  7.     def process(self, input_str: str) -> str:
  8.         """Process input data and return output data."""
  9.         pass
复制代码

  • 新建一个PluginManager, 并指定plugin manager需要的hookspec
注意这个plugin manager的名子也需要和实现规范保持一致,  都要叫"str2str"
  1. pm = pluggy.PluginManager("str2str")
  2. pm.add_hookspecs(Str2StrSpec)
复制代码

  • 新建一些插件.
在plugins目录下, 我们可以新建一些python文件实现相关的插件. 这里我们用@hookimpl显示指定了实现规范str2str所需的函数.
为了能够方便的自动加载, 我们写了一个register的方法, 调用这个方法可以把插件加入到plugin manager中.
注意这里需要手动指定插件的name, 否则register的时候会自动生成一个随机数做为name.
  1. import pluggy
  2. hookimpl = pluggy.HookimplMarker("str2str")
  3. class UpperCasePlugin:
  4.     @hookimpl
  5.     def process(self, input_str: str) -> str:
  6.         return input_str.upper()
  7.         
  8. plugin_name = 'upper'
  9. def register(pm):
  10.     pm.register(UpperCasePlugin(), name='upper')
  11. import pluggy
  12. hookimpl = pluggy.HookimplMarker("str2str")
  13. class ReversePlugin:
  14.     @hookimpl
  15.     def process(self, input_str: str) -> str:
  16.         return input_str[::-1]
  17. plugin_name = 'reverse'
  18. def register(pm):
  19.     pm.register(ReversePlugin(), name='reverse')
复制代码

  • 通过遍历目录下的py文件, 调用其中的register方法就可以把插件加载的plugin manager中. 随后, 我们可以用list_name_plugin显示插件的名子, 并可以手动调用特定插件.
  1. # 遍历 `plugins` 目录,自动导入并注册
  2. plugin_dir = pathlib.Path("plugins")
  3. for plugin_file in plugin_dir.glob("*.py"):
  4.     if plugin_file.stem != "__init__":
  5.         module_name = f"plugins.{plugin_file.stem}"
  6.         if module_name in sys.modules:
  7.             module = importlib.reload(sys.modules[module_name])
  8.         else:
  9.             module = importlib.import_module(module_name)
  10.         if hasattr(module, "register"):
  11.             plugin_name = module.plugin_name
  12.             pm.unregister(name=plugin_name)
  13.             module.register(pm)
  14.             
  15. print("已发现插件:", pm.list_name_plugin())
  16. pm.get_plugin(name='upper').process('hello')
  17. pm.get_plugin(name='reverse').process('hello')
复制代码

  • 稍加扩展, 我们就可以实现简单的python代码远程加载和更新功能.
  • 总结
  1. 组件        作用
  2. HookspecMarker("my_project")        定义 Hook 规范
  3. HookimplMarker("my_project")        标记插件实现
  4. PluginManager("my_project")        管理插件
复制代码
链接:
https://www.codebonobo.tech/post/21#%E7%94%A8pluggy%E5%AE%9E%E7%8E%B0%E5%8A%A8%E6%80%81%E8%BD%BD%E5%85%A5%E6%A8%A1%E5%9D%97

来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
您需要登录后才可以回帖 登录 | 立即注册