编程学习网 > 编程语言 > Python > python强大的hook函数教程
2023
07-11

python强大的hook函数教程

钩子函数(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.

以上就是python强大的hook函数教程的详细内容,想要了解更多Python教程欢迎持续关注编程学习网。

扫码二维码 获取免费视频学习资料

Python编程学习

查 看2022高级编程视频教程免费获取