MMCV核心组件:Hook

0 摘要

Hook 机制在 OpenMMLab 系列框架中应用非常广泛,结合 Runner 类可以实现对训练过程的整个生命周期进行管理。同时内置了多种 Hook,通过注册的形式注入 Runner 中实现了丰富的扩展功能,例如模型权重保存、日志记录等等。

1 Hook 通俗理解

(1)Hook是什么

在wiki百科中的定义如下:

钩子编程(hooking),也称作“挂钩”,是计算机程序设计语,指通过拦截软件模块间的函数调用、消息传递、事件传递来修改或扩展操作系统、应用程序或其他软件组件的行为的各种技术。处理被拦截的函数调用、事件、消息的代码,被称为(钩子hook)

简而言之,就是能改变程序执行流程的一种技术统称。

(2)Hook用途

Hook 技术应用非常广泛,可以随便找一个简单例子来说明其用途。在软件编程的设计模式中,有一种设计模式叫做观察者设计模式,该设计模式实现的功能是:对于被观察者的一举一动,观察者都能够立即观测到,其内部实现机制可以简单通过 hook 机制实现,下面具体说明。

假设气象台可以提供两种对外服务:各大城市未来五天的天气情况和是否会出现地质灾害,你下个月由于要出差想知道深圳未来五天的天气情况,很简单,只需要订阅该气象台发布的其中一个天气预报服务即可,然后每天早上八点你手机会自动收到气象台发布的天气情况,注意:你不需要每时每刻关注气象台是否有发布天气情况,而是等它通知即可,如果不想再收到天气预报了,那么取消订阅即可。

这是非常典型的观察者设计模式:被观察者(气象台)对外提供注册机制,观察者可以通过插入和移除 Hook 实现订阅和取消订阅消息的功能,无论观察者有没有注册 Hook,都不会影响被观察者发布消息,伪代码如下:

class 气象台():
    def __init__():
       self.天气预报服务=''
       self.是否存在地质灾害服务=''
       self.天气预报_hooks=[]
       self.是否存在地质灾害_hooks=[]

    def 订阅天气预报服务(hook_fn)
        self.天气预报_hooks.append(hook_fn) 

    def 取消订阅天气预报服务(hook_fn):
       del self.天气预报_hooks[hook_fn]

    def 订阅是否存在地质灾害服务(hook_fn)
        self.是否存在地质灾害_hooks.append(hook_fn) 

    def 取消订阅是否存在地质灾害服务(hook_fn):
       del self.是否存在地质灾害_hooks[hook_fn]

    # 每天早上8点,气象台自动调用
    def 发布消息():
      天气预报信息=获取天气信息()
      是否存在地质灾害信息=获取是否存在地质灾害信息()
      for hook in self.天气预报_hooks:
            hook(天气预报信息)
      for hook in self.是否存在地质灾害_hooks:
            hook(是否存在地质灾害信息)

针对个人用户气象台伪代码如下所示:

def 天气预报信息_hook(str):
    print(str)
    我收到消息了,天气预报内容是str


if __name__ == '__main__': 
   # 实例化
   气象台实例=气象台()
   # 注册 hook
   气象台实例.订阅天气预报服务(天气预报信息_hook)

   # 接收消息,此时我就能够自动收到消息了
   气象台实例.发布消息()

   # 不打算再订阅了
   气象台实例.取消订阅天气预报服务(天气预报信息_hook)

注意,实际上气象台实例不需要我们自己实例化,发布消息也不是我们控制的,这些都是被观察者自己的事情,个人用户只需要订阅和取消订阅即可。

在 python 中由于函数是一等公民,实现 hook 机制其实只需要传入一个函数即可,在该函数中我们可以获取到内部信息,可以修改或者访问该内容,从而实现一些类似黑科技一般的功能

(3)Hook如何用

在 python 中要实现 hook 机制,非常简单,传入一个函数即可,如下是一个简单的 hook,该 hook 的功能是打印内部变量

def hook(d):
   print(d)

def add(a,b,c,hook_fn=None):
   sum1=a+b
   if hook_fn is not None:
       hook_fn(sum1)
    return sum1+c

# 调用
add(1,2,3,hook)