Python中的钩子函数(hooks)介绍使用

news2024/11/16 18:02:30

什么是hook?

钩子函数,顾名思义,就是把我们自己实现的自定义函数在某一时刻挂接到目标挂载点上去执行。
1. hook函数,就是我们自己实现的函数,函数类型与挂载点匹配(返回值,参数列表)
2. 挂接,也就是hook或者叫注册(register),使得hook函数对目标可用
3. 目标挂载点,也就是挂我们hook函数的地方(我们想在这个目标点实现我们自己的功能)

hook是一种编程机制,与具体的编程语言无关。

为什么需要hook?

什么情况下需要实现hook?
—就是一个功能(类/方法)自身无法满足所有需求,那么可以通过hook 就提供扩展自身能力的可能

同一个需求平替实现

比如有个需求:获取每次请求后的请求状态码

方式1:原始做法直接在代码里增加

–不推荐,而且违反“开闭原则”

import requests
url = ' http://www.baidu.com'
r = requests.get(url)
print(f"status doce: {r.status_code}")

方式2:使用装饰器

import requests
# 定义装饰器
def print_status_code(func):
    def wrappers(*args, **kwargs):
        res = func(*args, **kwargs)
        print(f"Status code: {res.status_code}")
        return res
    return wrappers
@print_status_code
def send_request(url):
    res = requests.get(url)
    return res

url='https://httpbin.org/get'
send_request(url)

方式3:使用requests库自动hooks入参来使用钩子函数:将“获取请求状态的逻辑封装到一个函数中,在执行完请求后,就自动执行钩子函数"

import requests	没有参数
def custom_hooks(response,**kwargs):
	print(response.status_code)
def custom_hooks2(response,**kwargs):
	print(response.headers)
url = ' http://www.baidu.com'
response = requests.get(url, hooks={"response": [custom_hooks, custom_hooks2]})

钩子函数什么时候执行?

比如:response = requests.get(url, hooks={“response”: [custom_hooks, custom_hooks2]})
自定义的钩子函数在执行完请求后,执行钩子函数

实例:requests库的hooks介绍

requests提供了hook机制,让我们能够在请求得到响应之后,再去额外做一些自定义的操作,比如打印某些信息、修改响应内容等。

注意:

  1. requests库中钩子函数是在请求得到响应之后才去行的钩子函数
  2. 如下示例测试数据基于requests 2.25.1

requests库如何使用hooks来调用钩子函数?

import requests
# 钩子函数1
def print_url(r, **kwargs):
	print("raw_url "+r.url)
# 钩子函数2
def change_url(r, **kwargs):
	r.url = ' http://change.url'
	print("changed_url "+r.url)
	return r  # 其实没有这句话,也可以修改r.url,因为r是response对象而非普通数值,但requests官方似乎误认为回调函数一定要有return才能替换传入的数据
url = ' http://httpbin.org/cookies'
# 使用hooks形参来调用钩子函数
response = requests.get(url, hooks=dict(response=[print_url, change_url]))
print("result_url "+response.url)

注意:
1) 钩子函数中的**kwargs形参不能少,且必须是关键字参数
□ 因为在调用钩子函数时,requests.session.py实现了添加了相关参数 在这里插入图片描述2) requests.中的hook入参值类型必须是字典,且key必须是"response",value有多个时必须为list类型。
□ key必须是"response": 因为
①requests.hooks.py如下代码有校验
在这里插入图片描述
②requests.models.py有如下校验 在这里插入图片描述

requests库使用钩子函数时,如果钩子函数需要传递参数,如何向钩子函数传递参数?

有两种方式:
方式1: 使用偏函数(funtools.partial)过要注意,使用这种方式,不能适用于钩子函数有多个位置参数的情况,只适配与钩子函数有关键字参数的情况。所以要将钩子函数设计成def my_hook_func(response, **kwargs)这种形式。
因为当使用 functools.partial 结合 requests 库的钩子函数时,直接传递位置参数会干扰 requests 默认传递给钩子函数的参数顺序。 requests 库在调用钩子函数时,会将 response 对象作为第一个参数传入。如果使用 partial 传递位置参数,这些位置参数会占用钩子函数本来为 response 留下的位置,从而导致错误。
示例:

import requests
from functools import partial

# 定义钩子函数
def response_hook(response, **kwargs):
	print(f"所有关键字参数{kwargs}")
	parms1 = kwargs.get('parms1')
	parms2 = kwargs.get('parms2')
	print("额外参数2:", parms1)
	print("额外参数2:", parms2)
	print("响应状态码:", response.status_code)
	return response

# 使用 partial 来创建一个新的钩子函数,其中传入了关键字参数
hook_with_param = partial(response_hook, parms1='val1', parms2='val2')

# 进行请求,并传入钩子函数
response = requests.get('https://httpbin.org/get', hooks={'response': hook_with_param})

# 打印响应内容
print(response.text)

方式2:使用闭包
使用闭包比使用偏函数稍微麻烦一点,不过使用闭包能支持位置参数和关键字参数,这点要比偏函数好

import requests

# 定义一个外层函数来包裹钩子函数,从而传入额外的参数
def create_response_hook(extra_param, additional_arg, **kwargs2):
	def response_hook(response, *args, **kwargs):
		print(f"kwargs参数的值{kwargs}")
		print("响应状态码:", response.status_code)
		print("额外参数:", extra_param)
		print("额外位置参数:", additional_arg)
		print("额外关键字参数:", kwargs2)
		print("params1参数:", kwargs2.get("params1"))
		print("params2参数:", kwargs2.get("params2"))
		return response
	return response_hook

# 创建带有额外参数的钩子函数
hook_with_param = create_response_hook('额外的数据', '额外位置参数1', params1="val1", params2="val2")

# 进行请求,并传入钩子函数
response = requests.get('https://httpbin.org/get', hooks={'response': hook_with_param})

# 打印响应内容
print(response.text)


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1812631.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

virtual box安装invalid installation directory

问题原因 看官方文档Chapter 2. Installation Details 第2.1.2所示,安装目录需要满足两个条件: 一是:需要安装目录的所有父目录都要满足以下访问控制条件 Users S-1-5-32-545:(OI)(CI)(RX) Users S-1-5-32-545…

添加L1/L2损失函数,以及AttributeError: ‘NoneType‘ object has no attribute ‘data‘

添加L1/L2损失函数,以及解决报错 1.添加L1 loss2.添加L2 loss3.代码报错:AttributeError: NoneType object has no attribute data 1.添加L1 loss # 方式1:添加到损失函数中 def l1_regularization(model, l1_alpha):l1_loss []for module …

健康节能台灯的设计电子实践

1.1 功能描述 根据主要功能要求,该设计利用 51 单片机实现了电子时钟、温度的显示以 及整点报时等功能。具体可分为一下几种: 1) 显示当前的日期及时间,24 时制的时、分、秒; 2) 可调节时间; 3) 整点报时并响铃。 4) 能…

SpringCloud微服务架构(eureka、nacos、ribbon、feign、gateway等组件的详细介绍和使用)

一、微服务演变 1、单体架构(Monolithic Architecture) 是一种传统的软件架构模式,应用程序的所有功能和组件都集中在一个单一的应用中。 在单体架构中,应用程序通常由一个大型的、单一的代码库组成,其中包含了所有…

C/C++ 进阶(6)红黑树

个人主页:仍有未知等待探索-CSDN博客 专题分栏:C 目录 一、概念 性质 二、操作 插入 情况一:cur为红、p为红、g为黑,如果u存在且为红 步骤: 情况二:cur为红、p为红、g为黑,如果u不存在或…

京东网页html+css简单制作1(附带源码和素材)

一.代码效果展示 代码html骨架结构分为头部top,颈部banner,中间部分main,腿部fortet-image,尾部fortter,五部分组成,从上至下,从左到右结构。(总体因为没设计版心,所以位置比较乱) 其中中部mai…

迷宫最短路径求解--c++

【代码】 #include<iostream> #include<queue> #include<stack> using namespace std; #define ROW 8 #define COL 8 //测试迷宫数据 int maze[ROW][COL] {{0,0,0,1,0,0,0,0},{0,1,0,1,0,1,0,1},{0,1,0,0,0,1,0,1},{0,1,0,1,1,1,0,1},{0,1,0,1,1,0,0,0},{0…

第一百零四节 Java面向对象设计 - Java内部类成员

Java面向对象设计 - Java内部类成员 内部类可以访问其所有实例成员&#xff0c;实例字段和其封闭类的实例方法。 class Outer {private int value 2014;public class Inner {public void printValue() {System.out.println("Inner: Value " value);}} // Inner …

这三款思维导图工具,真的很好用

XMIND XMIND是优秀的国产思维导图和头脑风暴软件&#xff0c;非常符合国人的使用要求&#xff0c;旨在帮助用户理清思路、捕捉创意&#xff0c;并提高工作和生活效率。支持Linux、IOS、Android、MAC平台。 提供了非常多精美的结构图&#xff0c;例如鱼骨图、逻辑图、括号图、树…

Django DeleteView视图

Django 的 DeleteView 是一个基于类的视图&#xff0c;用于处理对象的删除操作。 1&#xff0c;添加视图函数 Test/app3/views.py from django.shortcuts import render# Create your views here. from .models import Bookfrom django.views.generic import ListView class B…

点云分割报告整理(未完成版-每天写一点)

体积占用网格表示对点进行体素化&#xff0c;然后使用3d卷积神经网络来学习体素级语义。由于点云的稀疏性&#xff0c;体素化效率低&#xff0c;为避免较高的计算成本而忽略了细节。此外&#xff0c;由于同一体素内的所有点都被赋予了相同的语义标签&#xff0c;因此精度受到限…

详解MySQL中的PERCENT_RANK函数

目录 1. 引入1. 基本使用2&#xff1a;分组使用3&#xff1a;处理重复值4. 使用优势4.1 手动计算百分等级4.2 使用 PERCENT_RANK 的优势4.3 使用 PERCENT_RANK 5. 总结 在 MySQL 中&#xff0c;PERCENT_RANK 函数用于计算一个值在其分组中的百分等级。 它的返回值范围是从 0 …

广州商学院数字经济产业学院领导莅临泰迪智能科技参观交流

6月6日&#xff0c;广州商学院数字经济产业学院主任潘鹏、专业负责人欧阳峰、专业老师刘宇宏莅临广东泰迪智能科技股份有限公司产教融合实训基地参观交流。泰迪智能科技董事长张良均、中职事业部总经理李振林、校企合作经理吴桂锋进行热情接待&#xff0c;双方就专业建设、人才…

超详解——深入详解Python基础语法——基础篇

目录 1 .语句和变量 变量赋值示例&#xff1a; 打印变量的值&#xff1a; 2. 语句折行 反斜杠折行示例&#xff1a; 使用括号自动折行&#xff1a; 3. 缩进规范 缩进示例&#xff1a; 4. 多重赋值&#xff08;链式赋值&#xff09; 多重赋值的应用&#xff1a; 5 .多…

20个国家科学数据中心(中)

7、国家极地科学数据中心平台 网址&#xff1a;http://www.chinare.org.cn 简介&#xff1a;国家极地科学数据中心&#xff08;www.chinare.org.cn&#xff0c;以下称"本网站或NADC网站&#xff09;的前身是中华人民共和国科技部1999年资助下建立的中国极地科学数据库系…

项目部署(前后端)

一&#xff1a;多环境概念&#xff1a; 借鉴来源&#xff1a;多环境设计_程序员鱼皮-多环境设计-CSDN博客 为什么需要多环境&#xff1a; 第一个例子&#xff1a;我们可以设想&#xff0c;我们肯定玩过王者荣耀&#xff0c;且王者荣耀也一直在不断更新&#xff0c;如果按我们…

STM32F103C8T6移植U8g2图形库及基于I2C协议的OLED显示(HAL库方式)【U8g2】【STM32开发板】【STM32CubeMX】

STM32F103C8T6移植U8g2图形库及基于I2C协议的OLED显示&#xff08;HAL库方式&#xff09;【U8g2】【STM32开发板】【STM32CubeMX】 实验说明 利用STM32F103的GPIO管脚、VCC和GND连接OLED屏的I2C接口&#xff0c;采用CubeMX设计一个HAL库程序框架&#xff0c;然后下载U8g2源码…

算法:94. 二叉树的中序遍历--扩展前中后层序遍历

中序遍历 给定一个二叉树的根节点 root &#xff0c;返回 它的 中序 遍历 。 中遍历结果为&#xff1a;H D I B E J A F K C G 示例 1&#xff1a; 输入&#xff1a;root [1,null,2,3] 输出&#xff1a;[1,3,2]示例 2&#xff1a; 输入&#xff1a;root [] 输出&#x…

图片二维码在线制作的教程,轻松实现图片转二维码

现在很多的内容都会放入二维码中来提供展示&#xff0c;这种方法可以有效的将大量的内容通过扫码这种简单的方式来获取。比如将图片转二维码后&#xff0c;就可以用手机扫码查看图片&#xff0c;无需通过软件传输后下载才可以查看&#xff0c;并且这种方式还可以提升图片的安全…

后端开发面经系列 -- 华为OD -- C++面经(全)

华为OD – C面经&#xff08;全&#xff09; 公众号&#xff1a;阿Q技术站 文章目录 华为OD -- C面经&#xff08;全&#xff09;一面1、C结构体和类的区别&#xff0c;类默认的访问权限&#xff0c;结构体可以定义成员函数吗&#xff1f;2、多态的意义&#xff1f;多态的意义…