返回顶部
首页 > 资讯 > 后端开发 > Python >Python pluggy模块如何使用
  • 708
分享到

Python pluggy模块如何使用

2023-06-30 13:06:12 708人浏览 薄情痞子

Python 官方文档:入门教程 => 点击学习

摘要

本篇内容介绍了“python pluggy模块如何使用”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!1 pluggy 简介plug

本篇内容介绍了“python pluggy模块如何使用”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!

1 pluggy 简介

  • pluggy 作用:提供了一个简易便捷的插件系统,可以做到插件与主题功能松耦合

  • pluggy 是pytest,tox,devpi的核心框架

2 安装

执行如下命令即可

pip install pluggy

3 使用初体验

import pluggy# HookspecMarker 和 HookimplMarker 实质上是一个装饰器带参数的装饰器类,作用是给函数增加额外的属性设置hookspec = pluggy.HookspecMarker("myproject")hookimpl = pluggy.HookimplMarker("myproject")# 定义自己的Spec,这里可以理解为定义接口类class MySpec:    # hookspec 是一个装饰类中的方法的装饰器,为此方法增额外的属性设置,这里myhook可以理解为定义了一个接口    @hookspec    def myhook(self, arg1, arg2):        pass# 定义了一个插件class Plugin_1:    # 插件中实现了上面定义的接口,同样这个实现接口的方法用 hookimpl装饰器装饰,功能是返回两个参数的和    @hookimpl    def myhook(self, arg1, arg2):        print("inside Plugin_1.myhook()")        return arg1 + arg2# 定义第二个插件class Plugin_2:    # 插件中实现了上面定义的接口,同样这个实现接口的方法用 hookimpl装饰器装饰,功能是返回两个参数的差    @hookimpl    def myhook(self, arg1, arg2):        print("inside Plugin_2.myhook()")        return arg1 - arg2# 实例化一个插件管理的对象,注意这里的名称要与文件开头定义装饰器的时候的名称一致pm = pluggy.PluginManager("myproject")# 将自定义的接口类加到钩子定义中去pm.add_hookspecs(MySpec)# 注册定义的两个插件pm.reGISter(Plugin_1())pm.register(Plugin_2())# 通过插件管理对象的钩子调用方法,这时候两个插件中的这个方法都会执行,而且遵循后注册先执行即LIFO的原则,两个插件的结果讲义列表的形式返回results = pm.hook.myhook(arg1=1, arg2=2)print(results)

执行结果如下:

inside Plugin_2.myhook()
inside Plugin_1.myhook()
[-1, 3]

4 详解解释

从代码上看比较绕,其实通俗一点理解,其实挺简单的,可以理解为首先定义一个接口类,然后定义很多插件类,插件类想要多少就定义多少, 接口类中要定义接口,上面的例子值定义了一个接口,其实可以定义很多接口,在每个插件类中需要选择接口类中的接口去实现,当然也不需要每个 都需要去实现,可以根据自己的需要有选择的去实现。

举个例子:

比如定义了一个接口类,接口类中定义了10个接口,同时定义了3个类,这三个类分别实现了接口类中3个接口,6个接口和10个接口,然后实例化一个插件管理的对象,实例化对象将接口类加入定义模板中,然后去注册这三个类,注册之后,就可以通过插件管理对象的钩子去调用接口类中的每个方法了,比如调用头三个方法,因为每个插件中都实现了,所以就会有三个结果,调用后面4-6的接口时,因为只有两个插件实现了,所以只会有两个结果返回,调用7-10的接口因为只有一个插件类实现了,所以就会只有一个结果返回,这样插件使用起来就非常灵活,可以真正做到“热插拔”

下面用代码示例演示:

import pluggy# HookspecMarker 和 HookimplMarker 实质上是一个装饰器带参数的装饰器类,作用是给函数增加额外的属性设置hookspec = pluggy.HookspecMarker("myproject")hookimpl = pluggy.HookimplMarker("myproject")# 定义自己的Spec,这里可以理解为定义接口类class MySpec:    # hookspec 是一个装饰类中的方法的装饰器,为此方法增额外的属性设置,这里myhook可以理解为定义了3个接口    @hookspec    def myhook1(self, arg1, arg2):        pass    @hookspec    def myhook2(self, arg1, arg2):        pass    @hookspec    def myhook3(self, arg1, arg2):        pass# 定义了一个插件class Plugin_1:    # 插件中实现了上面定义的接口,同样这个实现接口的方法用 hookimpl装饰器装饰,功能是返回两个参数的和    @hookimpl    def myhook1(self, arg1, arg2):        print("inside Plugin_1.myhook1()")        return arg1 + arg2    @hookimpl    def myhook2(self, arg1, arg2):        print("inside Plugin_1.myhook2()")        return arg1 + arg2 +1    @hookimpl    def myhook4(self, arg1, arg2):        print("inside Plugin_1.myhook4()")        return arg1 + arg2 + 2# 定义第二个插件class Plugin_2:    # 插件中实现了上面定义的接口,同样这个实现接口的方法用 hookimpl装饰器装饰,功能是返回两个参数的差    @hookimpl    def myhook1(self, arg1, arg2):        print("inside Plugin_2.myhook1()")        return arg1 - arg2    @hookimpl    def myhook2(self, arg1, arg2):        print("inside Plugin_2.myhook2()")        return arg1 - arg2 -1    @hookimpl    def myhook3(self, arg1, arg2):        print("inside Plugin_2.myhook3()")        return arg1 - arg2 -2# 实例化一个插件管理的对象,注意这里的名称要与文件开头定义装饰器的时候的名称一致pm = pluggy.PluginManager("myproject")# 将自定义的接口类加到钩子定义中去pm.add_hookspecs(MySpec)# 注册定义的两个插件pm.register(Plugin_1())pm.register(Plugin_2())# 通过插件管理对象的钩子调用方法,这时候两个插件中的这个方法都会执行,而且遵循后注册先执行即LIFO的原则,两个插件的结果讲义列表的形式返回results = pm.hook.myhook1(arg1=1, arg2=2)print(results)results = pm.hook.myhook2(arg1=1, arg2=2)print(results)results = pm.hook.myhook3(arg1=1, arg2=2)print(results)results = pm.hook.myhook4(arg1=1, arg2=2)print(results)

执行结果如下:

inside Plugin_2.myhook1()
inside Plugin_1.myhook1()
[-1, 3]
inside Plugin_2.myhook2()
inside Plugin_1.myhook2()
[-2, 4]
inside Plugin_2.myhook3()
[-3]
inside Plugin_1.myhook4()
[5]

从上面的代码示例可以看出:

  • 1)myhook1 和 myhook2 因为两个插件都实现了,所有返回两个结果,而且是倒序的

  • 2)myhook3 因为只有插件2实现了,所以只有一个返回结果

  • 3)myhook4 在spec中未定义,这里却也有结果,目前理解可能是pluggy的bug,待后续看源码后解释

5 HookspeckMarker装饰器支持传入一些特定的参数

当传入firstresult=True时,获取第一个plugin执行结果后就停止继续执行

import pluggy# HookspecMarker 和 HookimplMarker 实质上是一个装饰器带参数的装饰器类,作用是给函数增加额外的属性设置hookspec = pluggy.HookspecMarker("myproject")hookimpl = pluggy.HookimplMarker("myproject")# 定义自己的Spec,这里可以理解为定义接口类class MySpec:    # hookspec 是一个装饰类中的方法的装饰器,为此方法增额外的属性设置,这里myhook可以理解为定义了一个接口    @hookspec(firstresult=True)    def myhook(self, arg1, arg2):        pass# 定义了一个插件class Plugin_1:    # 插件中实现了上面定义的接口,同样这个实现接口的方法用 hookimpl装饰器装饰,功能是返回两个参数的和    @hookimpl    def myhook(self, arg1, arg2):        print("inside Plugin_1.myhook()")        return arg1 + arg2# 定义第二个插件class Plugin_2:    # 插件中实现了上面定义的接口,同样这个实现接口的方法用 hookimpl装饰器装饰,功能是返回两个参数的差    @hookimpl    def myhook(self, arg1, arg2):        print("inside Plugin_2.myhook()")        return arg1 - arg2# 实例化一个插件管理的对象,注意这里的名称要与文件开头定义装饰器的时候的名称一致pm = pluggy.PluginManager("myproject")# 将自定义的接口类加到钩子定义中去pm.add_hookspecs(MySpec)# 注册定义的两个插件pm.register(Plugin_1())pm.register(Plugin_2())# 通过插件管理对象的钩子调用方法,这时候两个插件中的这个方法都会执行,而且遵循后注册先执行即LIFO的原则,两个插件的结果讲义列表的形式返回results = pm.hook.myhook(arg1=1, arg2=2)print(results)

执行结果如下:

inside Plugin_2.myhook()
-1

6 HookImplMarker装饰器也支持传入一些特定的参数

常用的有tryfirst和trylast以及hookwrapper

  • 当传入tryfirst=True时,表示这个类的hook函数会优先执行,其他的仍然按照后进先出的顺序执行

import pluggy# HookspecMarker 和 HookimplMarker 实质上是一个装饰器带参数的装饰器类,作用是给函数增加额外的属性设置hookspec = pluggy.HookspecMarker("myproject")hookimpl = pluggy.HookimplMarker("myproject")# 定义自己的Spec,这里可以理解为定义接口类class MySpec:    # hookspec 是一个装饰类中的方法的装饰器,为此方法增额外的属性设置,这里myhook可以理解为定义了一个接口    @hookspec    def myhook(self, arg1, arg2):        pass# 定义了一个插件class Plugin_1:    # 插件中实现了上面定义的接口,同样这个实现接口的方法用 hookimpl装饰器装饰,功能是返回两个参数的和    @hookimpl(tryfirst=True)    def myhook(self, arg1, arg2):        print("inside Plugin_1.myhook()")        return arg1 + arg2# 定义第二个插件class Plugin_2:    # 插件中实现了上面定义的接口,同样这个实现接口的方法用 hookimpl装饰器装饰,功能是返回两个参数的差    @hookimpl    def myhook(self, arg1, arg2):        print("inside Plugin_2.myhook()")        return arg1 - arg2# 定义第三个插件class Plugin_3:    # 插件中实现了上面定义的接口,同样这个实现接口的方法用 hookimpl装饰器装饰,功能是返回两个参数的差    @hookimpl    def myhook(self, arg1, arg2):        print("inside Plugin_3.myhook()")        return arg1 - arg2+10# 实例化一个插件管理的对象,注意这里的名称要与文件开头定义装饰器的时候的名称一致pm = pluggy.PluginManager("myproject")# 将自定义的接口类加到钩子定义中去pm.add_hookspecs(MySpec)# 注册定义的两个插件pm.register(Plugin_1())pm.register(Plugin_2())pm.register(Plugin_3())# 通过插件管理对象的钩子调用方法,这时候两个插件中的这个方法都会执行,而且遵循后注册先执行即LIFO的原则,两个插件的结果讲义列表的形式返回results = pm.hook.myhook(arg1=1, arg2=2)print(results)

执行结果让如下:

inside Plugin_1.myhook()
inside Plugin_3.myhook()
inside Plugin_2.myhook()
[3, 9, -1]

  • 当传入trylast=True,表示当前插件的hook函数会尽可能晚的执行,其他的仍然按照后进先出的顺序执行

import pluggy# HookspecMarker 和 HookimplMarker 实质上是一个装饰器带参数的装饰器类,作用是给函数增加额外的属性设置hookspec = pluggy.HookspecMarker("myproject")hookimpl = pluggy.HookimplMarker("myproject")# 定义自己的Spec,这里可以理解为定义接口类class MySpec:    # hookspec 是一个装饰类中的方法的装饰器,为此方法增额外的属性设置,这里myhook可以理解为定义了一个接口    @hookspec    def myhook(self, arg1, arg2):        pass# 定义了一个插件class Plugin_1:    # 插件中实现了上面定义的接口,同样这个实现接口的方法用 hookimpl装饰器装饰,功能是返回两个参数的和    @hookimpl()    def myhook(self, arg1, arg2):        print("inside Plugin_1.myhook()")        return arg1 + arg2# 定义第二个插件class Plugin_2:    # 插件中实现了上面定义的接口,同样这个实现接口的方法用 hookimpl装饰器装饰,功能是返回两个参数的差    @hookimpl(trylast=True)    def myhook(self, arg1, arg2):        print("inside Plugin_2.myhook()")        return arg1 - arg2# 定义第三个插件class Plugin_3:    # 插件中实现了上面定义的接口,同样这个实现接口的方法用 hookimpl装饰器装饰,功能是返回两个参数的差    @hookimpl    def myhook(self, arg1, arg2):        print("inside Plugin_3.myhook()")        return arg1 - arg2+10# 实例化一个插件管理的对象,注意这里的名称要与文件开头定义装饰器的时候的名称一致pm = pluggy.PluginManager("myproject")# 将自定义的接口类加到钩子定义中去pm.add_hookspecs(MySpec)# 注册定义的两个插件pm.register(Plugin_1())pm.register(Plugin_2())pm.register(Plugin_3())# 通过插件管理对象的钩子调用方法,这时候两个插件中的这个方法都会执行,而且遵循后注册先执行即LIFO的原则,两个插件的结果讲义列表的形式返回results = pm.hook.myhook(arg1=1, arg2=2)print(results)

执行结果如下:

inside Plugin_3.myhook()
inside Plugin_1.myhook()
inside Plugin_2.myhook()
[9, 3, -1]

  • 当传入hookwrapper=True时,需要在这个plugin中实现一个yield,plugin先执行yield

之前的代码,然后去执行其他的pluggin,然后再回来执行yield之后的代码,同时通过yield可以 获取到其他插件执行的结果

import pluggy# HookspecMarker 和 HookimplMarker 实质上是一个装饰器带参数的装饰器类,作用是给函数增加额外的属性设置hookspec = pluggy.HookspecMarker("myproject")hookimpl = pluggy.HookimplMarker("myproject")# 定义自己的Spec,这里可以理解为定义接口类class MySpec:    # hookspec 是一个装饰类中的方法的装饰器,为此方法增额外的属性设置,这里myhook可以理解为定义了一个接口    @hookspec    def myhook(self, arg1, arg2):        pass# 定义了一个插件class Plugin_1:    # 插件中实现了上面定义的接口,同样这个实现接口的方法用 hookimpl装饰器装饰,功能是返回两个参数的和    @hookimpl()    def myhook(self, arg1, arg2):        print("inside Plugin_1.myhook()")        return arg1 + arg2# 定义第二个插件class Plugin_2:    # 插件中实现了上面定义的接口,同样这个实现接口的方法用 hookimpl装饰器装饰,功能是返回两个参数的差    @hookimpl(hookwrapper=True)    def myhook(self, arg1, arg2):        print("inside Plugin_2.myhook() before yield...")        output=yield        result=output.get_result()        print(result)        print("inside Plugin_2.myhook() after yield...")# 定义第三个插件class Plugin_3:    # 插件中实现了上面定义的接口,同样这个实现接口的方法用 hookimpl装饰器装饰,功能是返回两个参数的差    @hookimpl    def myhook(self, arg1, arg2):        print("inside Plugin_3.myhook()")        return arg1 - arg2+10# 实例化一个插件管理的对象,注意这里的名称要与文件开头定义装饰器的时候的名称一致pm = pluggy.PluginManager("myproject")# 将自定义的接口类加到钩子定义中去pm.add_hookspecs(MySpec)# 注册定义的两个插件pm.register(Plugin_1())pm.register(Plugin_2())pm.register(Plugin_3())# 通过插件管理对象的钩子调用方法,这时候两个插件中的这个方法都会执行,而且遵循后注册先执行即LIFO的原则,两个插件的结果讲义列表的形式返回results = pm.hook.myhook(arg1=1, arg2=2)print(results)

执行结果如下:

inside Plugin_2.myhook() before yield...
inside Plugin_3.myhook()
inside Plugin_1.myhook()
[9, 3]
inside Plugin_2.myhook() after yield...
[9, 3]

Python pluggy模块如何使用”的内容就介绍到这里了,感谢大家的阅读。如果想了解更多行业相关的知识可以关注编程网网站,小编将为大家输出更多高质量的实用文章!

--结束END--

本文标题: Python pluggy模块如何使用

本文链接: https://lsjlt.com/news/329343.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

猜你喜欢
  • Python pluggy模块如何使用
    本篇内容介绍了“Python pluggy模块如何使用”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!1 pluggy 简介plug...
    99+
    2023-06-30
  • Python pluggy模块的用法示例演示
    目录1 pluggy 简介2 安装3 使用初体验4 详解解释5 HookspeckMarker装饰器支持传入一些特定的参数6 HookImplMarker装饰器也支持传入一些特定的参...
    99+
    2024-04-02
  • python如何使用import模块
    这篇文章给大家分享的是有关python如何使用import模块的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。import模块在Python经常使用import声明,以使用其他模块...
    99+
    2024-04-02
  • 如何使用python xml模块
    本篇内容主要讲解“如何使用python xml模块”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“如何使用python xml模块”吧!一、xml简介xml是实现不同语言或程序之间进行数据交换的协...
    99+
    2023-06-07
  • python如何使用timeit模块
    这篇文章给大家分享的是有关python如何使用timeit模块的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。timeit模块timeit 模块提供了测量 Python 小段代码执行时间的方法,可以在命令行界面直接...
    99+
    2023-06-17
  • python如何使用itertools模块
    这篇文章主要为大家展示了“python如何使用itertools模块”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“python如何使用itertools模块”这篇文章吧。高效的itertools...
    99+
    2023-06-27
  • python ffmpeg模块如何使用
    要使用Python中的FFmpeg模块,可以按照以下步骤进行:1. 安装FFmpeg:在你的系统上安装FFmpeg。你可以从官方网站...
    99+
    2023-10-12
    python
  • Python async模块如何使用
    这篇文章主要介绍“Python async模块如何使用”,在日常操作中,相信很多人在Python async模块如何使用问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”Python ...
    99+
    2023-07-05
  • Python decimal模块如何使用
    这篇文章主要介绍“Python decimal模块如何使用”,在日常操作中,相信很多人在Python decimal模块如何使用问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”Python&...
    99+
    2023-07-05
  • Python中如何使用mongodb模块
    这篇文章给大家介绍Python中如何使用mongodb模块,内容非常详细,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。涉及到python和mongodb,那么安装相应的模块四必不可少的,最简单的安装...
    99+
    2024-04-02
  • python中如何使用os模块
    小编给大家分享一下python中如何使用os模块,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!python是什么意思Python是一种跨平台的、具有解释性、编译性...
    99+
    2023-06-14
  • python中os模块如何使用
    这篇文章主要介绍了python中os模块如何使用,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。python有哪些常用库python常用的库:1.requesuts;2.scr...
    99+
    2023-06-14
  • Python中 Collections 模块如何使用
    今天就跟大家聊聊有关Python中 Collections 模块如何使用,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。collections模块是一个不用不知道,一用就上瘾的模块。这...
    99+
    2023-06-15
  • Python中如何使用py2exe模块
    这期内容当中小编将会给大家带来有关Python中如何使用py2exe模块,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。我们先准备一个简单的pythonPythonhello.py# hello....
    99+
    2023-06-17
  • python中如何使用 String模块
    本篇文章为大家展示了python中如何使用 String模块,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。string成员常量:ascii_letters = 'abcd...
    99+
    2023-06-17
  • python中如何使用email模块
    python中如何使用email模块,相信很多没有经验的人对此束手无策,为此本文总结了问题出现的原因和解决方法,通过这篇文章希望你能解决这个问题。说明email模块支持发送的邮件内容包括纯文本、HTML内容、图片和附件。email模块有几种...
    99+
    2023-06-20
  • python中如何使用smtplib模块
    python中如何使用smtplib模块,针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。说明创建SMTP的操作对象,连接smtp目标服务器,可以是163、QQ等。根据您的账户...
    99+
    2023-06-20
  • Python中ConfigParser模块如何使用
    Python中ConfigParser模块如何使用,针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。在程序中使用配置文件来灵活的配置一些参数是一件很常见的事情,配置文件的解析并...
    99+
    2023-06-17
  • Python中base64模块如何使用
    Python中base64模块如何使用,很多新手对此不是很清楚,为了帮助大家解决这个难题,下面小编将为大家详细讲解,有这方面需求的人可以来学习下,希望你能有所收获。Python base64模块是用来作base64编码解码的。这种编码方式在...
    99+
    2023-06-17
  •  Python中logging模块如何使用
    这篇文章主要讲解了“ Python中logging模块如何使用”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“ Python中logging模块如何使用”吧!1.为什么要用...
    99+
    2023-06-29
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作