我的编程空间,编程开发者的网络收藏夹
学习永远不晚

Python pluggy模块如何使用

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

Python pluggy模块如何使用

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

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

Python pluggy模块如何使用

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

Python pluggy模块如何使用

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

如何使用python xml模块

本篇内容主要讲解“如何使用python xml模块”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“如何使用python xml模块”吧!一、xml简介xml是实现不同语言或程序之间进行数据交换的协
2023-06-07

Python async模块如何使用

这篇文章主要介绍“Python async模块如何使用”,在日常操作中,相信很多人在Python async模块如何使用问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”Python async模块如何使用”的疑
2023-07-05

python如何使用timeit模块

这篇文章给大家分享的是有关python如何使用timeit模块的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。timeit模块timeit 模块提供了测量 Python 小段代码执行时间的方法,可以在命令行界面直接
2023-06-17

python ffmpeg模块如何使用

要使用Python中的FFmpeg模块,可以按照以下步骤进行:1. 安装FFmpeg:在你的系统上安装FFmpeg。你可以从官方网站(http://ffmpeg.org/)上下载最新的版本,并按照说明进行安装。2. 安装ffmpeg-pyt
2023-10-12

Python decimal模块如何使用

这篇文章主要介绍“Python decimal模块如何使用”,在日常操作中,相信很多人在Python decimal模块如何使用问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”Python decimal模块如
2023-07-05

python如何使用itertools模块

这篇文章主要为大家展示了“python如何使用itertools模块”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“python如何使用itertools模块”这篇文章吧。高效的itertools
2023-06-27

Python Beautiful Soup模块如何使用

本文小编为大家详细介绍“Python Beautiful Soup模块如何使用”,内容详细,步骤清晰,细节处理妥当,希望这篇“Python Beautiful Soup模块如何使用”文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一起来
2023-07-05

python中如何使用smtplib模块

python中如何使用smtplib模块,针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。说明1、创建SMTP的操作对象,连接smtp目标服务器,可以是163、QQ等。2、根据
2023-06-20

python中如何使用 String模块

本篇文章为大家展示了python中如何使用 String模块,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。string成员常量:ascii_letters = abcdefghijklmnopqrs
2023-06-17

 Python中logging模块如何使用

这篇文章主要讲解了“ Python中logging模块如何使用”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“ Python中logging模块如何使用”吧!1.为什么要用logging模块在
2023-06-29

python中utils模块如何使用

在Python中,utils模块通常是一个包含一些常用的工具函数的模块。要使用utils模块中的功能,首先需要导入该模块:import utils然后就可以调用utils模块中的函数了。例如,假设utils模块中有一个名为print_me
python中utils模块如何使用
2024-04-03

Python中 Collections 模块如何使用

今天就跟大家聊聊有关Python中 Collections 模块如何使用,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。collections模块是一个不用不知道,一用就上瘾的模块。这
2023-06-15

Python中如何使用py2exe模块

这期内容当中小编将会给大家带来有关Python中如何使用py2exe模块,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。1.我们先准备一个简单的pythonPythonhello.py# hello.py
2023-06-17

python中threading模块如何使用

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

python的argparse模块如何使用

这篇文章主要介绍“python的argparse模块如何使用”,在日常操作中,相信很多人在python的argparse模块如何使用问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”python的argparse
2023-07-05

Python中ConfigParser模块如何使用

Python中ConfigParser模块如何使用,针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。在程序中使用配置文件来灵活的配置一些参数是一件很常见的事情,配置文件的解析并
2023-06-17

编程热搜

  • Python 学习之路 - Python
    一、安装Python34Windows在Python官网(https://www.python.org/downloads/)下载安装包并安装。Python的默认安装路径是:C:\Python34配置环境变量:【右键计算机】--》【属性】-
    Python 学习之路 - Python
  • chatgpt的中文全称是什么
    chatgpt的中文全称是生成型预训练变换模型。ChatGPT是什么ChatGPT是美国人工智能研究实验室OpenAI开发的一种全新聊天机器人模型,它能够通过学习和理解人类的语言来进行对话,还能根据聊天的上下文进行互动,并协助人类完成一系列
    chatgpt的中文全称是什么
  • C/C++中extern函数使用详解
  • C/C++可变参数的使用
    可变参数的使用方法远远不止以下几种,不过在C,C++中使用可变参数时要小心,在使用printf()等函数时传入的参数个数一定不能比前面的格式化字符串中的’%’符号个数少,否则会产生访问越界,运气不好的话还会导致程序崩溃
    C/C++可变参数的使用
  • css样式文件该放在哪里
  • php中数组下标必须是连续的吗
  • Python 3 教程
    Python 3 教程 Python 的 3.0 版本,常被称为 Python 3000,或简称 Py3k。相对于 Python 的早期版本,这是一个较大的升级。为了不带入过多的累赘,Python 3.0 在设计的时候没有考虑向下兼容。 Python
    Python 3 教程
  • Python pip包管理
    一、前言    在Python中, 安装第三方模块是通过 setuptools 这个工具完成的。 Python有两个封装了 setuptools的包管理工具: easy_install  和  pip , 目前官方推荐使用 pip。    
    Python pip包管理
  • ubuntu如何重新编译内核
  • 改善Java代码之慎用java动态编译

目录