钩子函数(hook function),可以理解是一个挂钩,作用是有需要的时候挂一个东西上去。具体的解释是:钩子函数是把我们自己实现的hook函数在某一时刻挂接到目标挂载点上。
hook应用场景
相信你对钩子函数并不陌生。我在 requests 和 mitmproxy 都有看到类似的设计。
requests 使用hook
例如 requests 中需要打印状态码:
# requests_hooks.py
import requests
r = requests.get("https://httpbin.org/get")
print(f"status doce: {r.status_code}")
打印状态码,这个动作,我们可以封装到一个函数里,然后作为钩子函数传给requests 使用。
# requests_hooks.py
import requests
def status_code(response, *args, **kwargs):
print(f"hook status doce: {response.status_code}")
r = requests.get("https://httpbin.org/get", hooks={"response": status_code})
代码说明:
把打印状态码封装到一个status_code() 函数中,在requests.get() 方法中通过hooks 参数接收钩子函数status_code()。
运行结果:
> python requests_hooks.py
hook status doce: 200
status_code() 作为一个函数,可以做的事情很多,比如,进一步判断状态码,打印响应的数据,甚至对相应的数据做加解密等处理。
mitmproxy 中的hook
mitmproxy是一个代理工具,我们这之前的文章也有做过介绍。在抓包的过程中,同样需要用到 hooks 去对request请求或response响应做一些额外的处理。
# anatomy.py
"""
Basic skeleton of a mitmproxy addon.
Run as follows: mitmproxy -s anatomy.py
"""
import logging
class Counter:
def __init__(self):
self.num = 0
def request(self, flow):
self.num = self.num + 1
logging.info("We've seen %d flows" % self.num)
addons = [Counter()]
运行mitmproxy
> mitmproxy -s anatomy.py
自己实现hook
什么情况下需要实现hook,就是一个功能(类/方法)自身无法满足所有需求,那么可以通过hook 就提供扩展自身能力的可能。
实现hook 并不难,看例子:
import time
class Programmer(object):
"""程序员"""
def __init__(self, name):
self.name = name
self.hooks_func = None
self.now_date = time.strftime("%Y-%m-%d")
def get_to_eat(self):
print(f"{self.name} - {self.now_date}: eat.")
def go_to_code(self):
print(f"{self.name} - {self.now_date}: code.")
def go_to_sleep(self):
print(f"{self.name} - {self.now_date}: sleep.")
def register_hook(self, hooks_func):
self.hooks_func = hooks_func
def everyday(self):
# 程序员日常三件事
self.get_to_eat()
self.go_to_code()
self.go_to_sleep()
# check the register_hook(hooked or unhooked)
# hooked
if self.hooks_func is not None:
self.hooks_func(self.name)
def play_game(name):
now_date = time.strftime("%Y-%m-%d")
print(f"{name} - {now_date}: play game.")
def shopping(name):
now_date = time.strftime("%Y-%m-%d")
print(f"{name} - {now_date}: shopping.")
if __name__ == "__main__":
tom = Programmer("Tom")
jerry = Programmer("Jerry")
spike = Programmer("Spike")
# 注册hook
tom.register_hook(play_game)
jerry.register_hook(shopping)
# 今日事情
tom.everyday()
jerry.everyday()
spike.everyday()
代码说明:
在上面的例子中Programmer类实现三个功能:eat、code、sleep,但程序员也是普通人,不能每天都只吃饭、编码、睡觉,于是通过register_hook() 提供了做别的事情的能力。
那么,看看Tom、Jerry、Spike三位主角,今天都干了什么吧!
运行结果:
Tom - 2022-12-01: eat.
Tom - 2022-12-01: code.
Tom - 2022-12-01: sleep.
Tom - 2022-12-01: play game.
Jerry - 2022-12-01: eat.
Jerry - 2022-12-01: code.
Jerry - 2022-12-01: sleep.
Jerry - 2022-12-01: shopping.
Spike - 2022-12-01: eat.
Spike - 2022-12-01: code.
Spike - 2022-12-01: sleep.
扫码二维码 获取免费视频学习资料
- 本文固定链接: http://phpxs.com/post/11169/
- 转载请注明:转载必须在正文中标注并保留原文链接
- 扫码: 扫上方二维码获取免费视频资料
查 看2022高级编程视频教程免费获取