什么是 hook (钩子)函数
经常会听到钩子函数(hook function)这个概念,最近在看目标检测开源框架mmdetection,里面也出现大量Hook的编程方式,那到底什么是hook?hook的作用是什么?
- what is hook ?钩子hook,顾名思义,可以理解是一个挂钩,作用是有需要的时候挂一个东西上去。具体的解释是:钩子函数是把我们自己实现的hook函数在某一时刻挂接到目标挂载点上。
- hook函数的作用 举个例子,hook的概念在windows桌面软件开发很常见,特别是各种事件触发的机制; 比如C++的MFC程序中,要监听鼠标左键按下的时间,MFC提供了一个onLeftKeyDown的钩子函数。很显然,MFC框架并没有为我们实现onLeftKeyDown具体的操作,只是为我们提供一个钩子,当我们需要处理的时候,只要去重写这个函数,把我们需要操作挂载在这个钩子里,如果我们不挂载,MFC事件触发机制中执行的就是空的操作。
从上面可知
- hook函数是程序中预定义好的函数,这个函数处于原有程序流程当中(暴露一个钩子出来)
- 我们需要再在有流程中钩子定义的函数块中实现某个具体的细节,需要把我们的实现,挂接或者注册(register)到钩子里,使得hook函数对目标可用
- hook 是一种编程机制,和具体的语言没有直接的关系
- 如果从设计模式上看,hook模式是模板方法的扩展
- 钩子只有注册的时候,才会使用,所以原有程序的流程中,没有注册或挂载时,执行的是空(即没有执行任何操作)
hook函数和我们常听到另外一个名称:回调函数(callback function)功能是类似的,可以按照同种模式来理解。
比如说你写了一个框架类的程序,你希望这个框架可以“被其他的代码注入”,即别人可以加入代码对你这个框架进行定制化,该如何做比较好?
一种很常见的方式就是约定一个规则,框架初始化时会收集满足这个规则的所有代码(文件),然后把这些代码加入到框架中来,在执行时一并执行。所有这一规则下可以被框架收集到的方法就是hook方法。
pytest 加载插件的方式
- 内置plugins:从代码内部的_pytest目录加载
- 外部插件(第三方插件):通过setuptools entry points机制发现的第三方插件模块
推荐的第三方的pytest的插件:How to install and use plugins - pytest documentation - conftest.py形式的本地插件:测试目录下的自动模块发现机制
查看当前pytest中所有的插件
pytest --trace-config
命令可以查看当前pytest中所有的plugin。
hook函数分类
第一部分:setuptools
引导挂钩要求足够早注册的插件(内部和setuptools插件),可以使用的钩子
- pytest_load_initial_conftests(early_config,parser,args): 在命令行选项解析之前实现初始conftest文件的加载。
- pytest_cmdline_preparse(config,args): (不建议使用)在选项解析之前修改命令行参数。
- pytest_cmdline_parse(pluginmanager,args): 返回一个初始化的配置对象,解析指定的args。
- pytest_cmdline_main(config): 要求执行主命令行动作。默认实现将调用configure hooks和runtest_mainloop。
第二部分: 初始化挂钩
初始化钩子需要插件和conftest.py文件
- pytest_addoption(parser): 注册argpa