代码为例进行说明

实践环境

Python 3.6.5

pluggy 0.13.0

例1 注册类函数为插件函数

#!/usr/bin/env python
# -*- coding:utf-8 -*- import pluggy hookspec = pluggy.HookspecMarker("myproject") # hook 标签 用于标记hook
hookimpl = pluggy.HookimplMarker("myproject") # hook 实现标签 用于标记hook的一个或多个实现 class MySpec(object):
"""hook 集合""" @hookspec
def myhook(self, arg1, arg2):
pass @hookspec
def my_hook_func1(self, arg1, arg2):
pass @hookspec
def my_hook_func2(self, arg1, arg2):
pass # 插件类
class Plugin_1(object):
"""hook实现类1""" @hookimpl
def myhook(self, arg1, arg2):
print("Plugin_1.myhook called")
return arg1 + arg2 @hookimpl
def my_hook_func2(self, arg1, arg2):
print("Plugin_1.my_hook_func2 called, args:", arg1, arg2) def my_hook_func3(self, arg1, arg2):
print("Plugin_1.my_hook_func3 called, args:", arg1, arg2) class Plugin_2(object):
"""hook实现类2""" @hookimpl
def myhook(self, arg1, arg2):
print("Plugin_2.myhook called")
return arg1 - arg2 @hookimpl
def my_hook_func2(self, arg1, arg2):
print("Plugin_2.my_hook_func2, args:", arg1, arg2) # 初始化 PluginManager
pm = pluggy.PluginManager("myproject") # 登记hook集合(hook函数声明)
pm.add_hookspecs(MySpec) # 注册插件(hook函数实现)
pm.register(Plugin_1())
pm.register(Plugin_2()) # 调用自定义hook
results = pm.hook.myhook(arg1=1, arg2=2) # 调用两个插件类中的同名hook函数 # 后注册的插件中的函数会先被调用
print(results) # 输出 [-1, 3] results = pm.hook.my_hook_func1(arg1="name", arg2="shouke")
print(results) pm.hook.my_hook_func2(arg1="addr", arg2="sz")

运行结果

Plugin_2.myhook called
Plugin_1.myhook called
[-1, 3]
[]
Plugin_2.my_hook_func2, args: addr sz
Plugin_1.my_hook_func2 called, args: addr sz

例2 注册模块函数为插件函数

myhookspec.pymyhookimpl.pyother.pyexample.py位于同一包目录下

myhookspec.py

import pluggy

hookspec = pluggy.HookspecMarker("myproject")  # hook 标签 用于标记hook
hookimpl = pluggy.HookimplMarker("myproject") # hook 实现标签 用于标记hook的一个或多个实现 @hookspec
def global_hook_func1(arg1, arg2):
pass

myhookimpl.py

import pluggy

from myhookspec import hookimpl

@hookimpl
def global_hook_func1(arg1, arg2):
print("global_hook_func1 in myhookimpl.py, args:", arg1, arg2)
return "myhookimpl.py"

other.py

from myhookspec import hookimpl

@hookimpl
def global_hook_func1(arg1, arg2):
print("global_hook_func1 in other.py, args:", arg1, arg2)
return "other.py"

example.py

#!/usr/bin/env python
# -*- coding:utf-8 -*- import sys
import pluggy
import myhookspec
import myhookimpl
import other # 初始化 PluginManager
pm = pluggy.PluginManager("myproject") # 登记hook集合
pm.add_hookspecs(myhookspec) # 登记hook的实现
pm.register(myhookimpl) # 插件也可以是模块
pm.register(other) print(pm.hook.global_hook_func1(arg1="name", arg2="shouke"))

example.py运行结果如下

global_hook_func1 in other.py, args: name shouke
global_hook_func1 in myhookimpl.py, args: name shouke
['other.py', 'myhookimpl.py']

例3:自定义插件类实现hook函数免@hookimpl装饰器

myhookspec.py

import pluggy

hookspec = pluggy.HookspecMarker("myproject")

@hookspec
def mytest_hook_func1(arg1, arg2):
pass

other.py

def mytest_hook_func1(arg1, arg2):
print("global_hook_func1 in other.py, args:", arg1, arg2)
return "other.py"

example.py

#!/usr/bin/env python
# -*- coding:utf-8 -*- import inspect
import pluggy
import myhookspec
import other class PytestPluginManager(pluggy.PluginManager):
"""
插件类,实现不用@HookimplMarkerInstance装饰的函数也可以当做函数体
""" def parse_hookimpl_opts(self, plugin, name):
# 规定免@hookimpl装饰的 hooks 函数总是以 mytest_打头,这样以避免访问非可读属性 if not name.startswith("mytest_"):
return method = getattr(plugin, name)
opts = super().parse_hookimpl_opts(plugin, name) # 考虑hook只能为函数(consider only actual functions for hooks)
if not inspect.isroutine(method):
return # 收集未被标记的,以mytest打头的hook函数,(collect unmarked hooks as long as they have the `pytest_' prefix)
if opts is None and name.startswith("mytest_"):
opts = {}
return opts # 初始化 PluginManager
pm = PytestPluginManager("myproject") # 登记hook集合
pm.add_hookspecs(myhookspec) # 登记hook的实现
pm.register(other) pm.hook.mytest_hook_func1(arg1="addr", arg2="sz")

参考连接

https://pypi.org/project/pluggy/

Python pluggy框架基础用法总结的更多相关文章

  1. Python Numpy shape 基础用法(转自他人的博客,如涉及到侵权,请联系我)

    Python Numpy shape 基础用法 shape函数是numpy.core.fromnumeric中的函数,它的功能是读取矩阵的长度,比如shape[0]就是读取矩阵第一维度的长度.它的输入 ...

  2. Python学习---Python的框架基础学习

    框架基础 框架实质: 所有的Web应用,本质上其实就是一个socket服务端,用户的浏览器其实就是一个socket客户端 B/S结构的响应: import socket def handle_requ ...

  3. python内建函数isinstance基础用法

      语法:isinstance(object,type) 作用:来判断一个对象是否是一个已知的类型.  其第一个参数(object)为对象,第二个参数(type)为类型名(int...)或类型名的一个 ...

  4. python bottle框架(WEB开发、运维开发)教程

    教程目录 一:python基础(略,基础还是自己看书学吧) 二:bottle基础 python bottle web框架简介 python bottle 框架环境安装 python bottle 框架 ...

  5. Python云端系统开发入门——框架基础

    Django框架基础 这是我学习北京理工大学嵩天老师的<Python云端系统开发入门>课程的笔记,在此我特别感谢老师的精彩讲解和对我的引导. 1.Django简介与安装 Django是一个 ...

  6. 【Python爬虫】selenium基础用法

    selenium 基础用法 阅读目录 初识selenium 基本使用 查找元素 元素互交操作 执行JavaScript 获取元素信息 等待 前进后退 Cookies 选项卡管理 异常处理 初识sele ...

  7. Python web框架 Tornado(一)基础学习

    概述 Tornado 是 FriendFeed 使用的可扩展的非阻塞式 web 服务器及其相关工具的开源版本.这个 Web 框架看起来有些像web.py 或者 Google 的 webapp,不过为了 ...

  8. 零基础小白必看篇:从0到1构建Python Web框架

    造轮子是最好的一种学习方式,本文尝试从0开始造个Python Web框架的轮子,我称它为ToyWebF. 本文操作环境为:MacOS,文中涉及的命令,请根据自己的系统进行替换. ToyWebF的简单特 ...

  9. Python测试框架pytest入门基础

    Pytest简介 Pytest is a mature full-featured Python testing tool that helps you write better programs.T ...

  10. 爬虫之Scrapy框架介绍及基础用法

    今日内容概要 爬虫框架之Scrapy 利用该框架爬取博客园 并发编程 今日内容详细 爬虫框架Scrapy 1.什么是框架? 框架类似于房子的结构,框架会提前帮你创建好所有的文件和内部环境 你只需要往对 ...

随机推荐

  1. acedCommand 之使用镜像命令

    ads_name ent; ads_point pt2, pt3; if (acedSSGet(NULL, NULL, NULL, NULL, ent) != RTNORM) { return; } ...

  2. nginx源码安装步骤

    1.安装依赖包 yum install -y gcc yum install -y pcre pcre-devel yum install -y zlib zlib-devel yum install ...

  3. Python的进程和线程——一些基础概念

    1. 线程和进程 1.1 线程和进程 进程可以包含多个并行运行的线程: 通常,操作系统创建和管理线程比进程更省CPU资源: 线程用于一些小任务,进程用于繁重的任务: 同一个进程下的线程共享地址空间和其 ...

  4. GIT文件上传演示

    Be Written By Handat.憨大头 注:以下内容默认你已经做好了git工具的用户账户配置. (1)创建Gitee线上代码仓库,HTTPS协议地址就是仓库地址,如例https://gite ...

  5. python获取豆瓣电影TOP250的所有电影的相关信息

    参考文档:https://weread.qq.com/web/reader/37132a705e2b2f37196c138k98f3284021498f137082c2e 说明:我才接触网络爬虫,在看 ...

  6. 微信小程序-手持弹幕_文字内容横屏滚动_小程序弹幕源码

    哈喽,大家好,我是SCLQ. 最近在抖音刷到手持弹幕的视频,觉得是一个非常有趣应用,在手持弹幕小程序这个软件当中,你可以设置很长一段话,很适合追星.挑战一下自己,做一个小程序的手持弹幕应用. 微信小程 ...

  7. INFINI Labs 产品更新 | Easysearch 1.8.2 发布优化 CCR 性能

    INFINI Labs 产品又更新啦~,包括 Easysearch v1.8.0.Gateway.Console.Agent.Loadgen v1.25.0.本次各产品更新了很多亮点功能,如 Easy ...

  8. el-upload拍照上传多个文件报错 ERR_UPLOAD_FILE_CHANGED问题

    最近同事使用el-upload上传图片时出现一个问题,连续拍照多个图片的时候,循环调用接口上传会报错: ERR_UPLOAD_FILE_CHANGED,网上找了很多方案没有解决,下面是我自己的解决过程 ...

  9. Big Exponential Addition

    Big Exponential Addition 给定一非负整数n计算2^n的值,一般而言把 2 乘上 n 次,就能得到答案.然而,当n特别大时,2^n要一次次地乘2可能稍嫌太慢,面对此一巨大问题利用 ...

  10. 10-Python进程与线程

    Python进程 创建新进程 from multiprocessing import Process import time def run_proc(name): #子进程要执行的代码 for i ...