什么是 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