Python pluggy框架基础用法总结

简介: Python pluggy框架基础用法总结

代码为例进行说明

实践环境

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/

目录
相关文章
|
10天前
|
中间件 数据库连接 API
Python面试:FastAPI框架原理与实战
【4月更文挑战第18天】FastAPI是受欢迎的高性能Python Web框架,以其简洁的API设计、强大的类型提示和优秀的文档生成能力著称。本文将探讨FastAPI面试中的常见问题,包括路由、响应对象、Pydantic模型、数据库操作、中间件和错误处理。同时,还会指出一些易错点,如类型提示不准确、依赖注入误解,并提供实战代码示例。通过理解和实践FastAPI,可以在面试中展示出色的Web开发技能。
23 1
|
10天前
|
API 数据库 数据安全/隐私保护
Flask框架在Python面试中的应用与实战
【4月更文挑战第18天】Django REST framework (DRF) 是用于构建Web API的强力工具,尤其适合Django应用。本文深入讨论DRF面试常见问题,包括视图、序列化、路由、权限控制、分页过滤排序及错误处理。同时,强调了易错点如序列化器验证、权限认证配置、API版本管理、性能优化和响应格式统一,并提供实战代码示例。了解这些知识点有助于在Python面试中展现优秀的Web服务开发能力。
24 1
|
1天前
|
Python
python web框架fastapi模板渲染--Jinja2使用技巧总结
python web框架fastapi模板渲染--Jinja2使用技巧总结
|
1天前
|
开发框架 网络协议 前端开发
Python高性能web框架--Fastapi快速入门
Python高性能web框架--Fastapi快速入门
|
1天前
|
Python 容器
Python中的for循环用法详解,一文搞定它
Python中的for循环用法详解,一文搞定它
|
1天前
|
网络协议 数据库 开发者
构建高效Python Web应用:异步编程与Tornado框架
【4月更文挑战第29天】在Web开发领域,响应时间和并发处理能力是衡量应用性能的关键指标。Python作为一种广泛使用的编程语言,其异步编程特性为创建高性能Web服务提供了可能。本文将深入探讨Python中的异步编程概念,并介绍Tornado框架如何利用这一机制来提升Web应用的性能。通过实例分析,我们将了解如何在实际应用中实现高效的请求处理和I/O操作,以及如何优化数据库查询,以支持更高的并发用户数和更快的响应时间。
|
6天前
|
安全 前端开发 JavaScript
在Python Web开发过程中:Web框架相关,如何在Web应用中防止CSRF攻击?
在Python Web开发中防范CSRF攻击的关键措施包括:验证HTTP Referer字段、使用CSRF token、自定义HTTP头验证、利用Web框架的防护机制(如Django的`{% csrf_token %}`)、Ajax请求时添加token、设置安全会话cookie及教育用户提高安全意识。定期进行安全审计和测试以应对新威胁。组合运用这些方法能有效提升应用安全性。
14 0
|
7天前
|
开发框架 前端开发 数据库
Python从入门到精通:3.3.2 深入学习Python库和框架:Web开发框架的探索与实践
Python从入门到精通:3.3.2 深入学习Python库和框架:Web开发框架的探索与实践
|
7天前
|
数据采集 数据可视化 数据处理
Python从入门到精通的文章3.3.1 深入学习Python库和框架:数据处理与可视化的利器
Python从入门到精通的文章3.3.1 深入学习Python库和框架:数据处理与可视化的利器
|
7天前
|
机器学习/深度学习 缓存 程序员
Python包管理工具 pip 及其常用命令和参数用法
Python包管理工具 pip 及其常用命令和参数用法
49 0