前言
本文主要讲述Python 探针的实现原理,为了验证,我们会来实现一个简单的统计指定函数执行时间的探针程序。
探针的实现主要涉及以下几个知识点:
1、sys.meta_path
2、sitecustomize.py
sys.meta_path 这个简单来说就是可以实现 import hook 的功能。
当执行 import 相关的操作时,会触发 sys.meta_path 列表中定义的对象。
关于 sys.meta_path 更详细的资料请查阅 python 文档中 sys.meta_path 相关内容以及PEP 0302 。
sys.meta_path 中的对象需要实现一个 find_module 方法。
这个 find_module 方法返回 None 或一个实现了 load_module 方法的对象。
import sys
class MetaPathFinder:
def find_module(self, fullname, path=None):
print('find_module {}'.format(fullname))
return MetaPathLoader()
class MetaPathLoader:
def load_module(self, fullname):
print('load_module {}'.format(fullname))
sys.modules[fullname] = sys
return sys
sys.meta_path.insert(0, MetaPathFinder())
if __name__ == '__main__':
import http
print(http)
print(http.version_info)
load_module 方法返回一个 module 对象,这个对象就是 import 的 module 对象了。
比如我上面那样就把 http 替换为 sys 这个 module 了。
$ python meta_path1.py
find_module http
load_module http
sys.version_info(major=3, minor=5, micro=1, releaselevel='final', serial=0)
通过 sys.meta_path 我们就可以实现 import hook 的功能:
当 import 预定的 module 时,对这个 module 里的对象来个狸猫换太子。
从而实现获取函数或方法的执行时间等探测信息。
上面说到了狸猫换太子,那么怎么对一个对象进行狸猫换太子的操作呢?
对于函数对象,我们可以使用装饰器的方式来替换函数对象。
import functools
import time
def func_wrapper(func):
@func