如何为被装饰器包装的函数使用line_profiler进行行级性能分析?
解决line_profiler分析装饰器包装函数时识别错误的问题
当使用line_profiler对被装饰器包装的函数做行级性能分析时,即便用了@wraps(func)保留原函数元信息,直接调用add_function(d)实际是把包装器wrapper加入分析队列,而非目标函数d本身。
修复方法:直接指定原始函数
利用@wraps给包装器添加的__wrapped__属性,获取被包装的原始目标函数,将其传入add_function:
修改原代码中的这一行:
lprofiler.add_function(d)
替换为:
lprofiler.add_function(d.__wrapped__)
修改后的完整代码:
from line_profiler import LineProfiler def a(): print("a") from functools import wraps def decorate(func): @wraps(func) def wrapper(*args, **kwargs): r = func(*args, **kwargs) print("decorating") return r return wrapper @decorate def d(): print("d") def go(): a() d() lprofiler = LineProfiler() lprofiler.add_function(a) # 改为添加原始函数 lprofiler.add_function(d.__wrapped__) lp_wrapper = lprofiler(go) lp_wrapper() lprofiler.print_stats()
效果说明
修改后运行代码,line_profiler会正确分析目标函数d的行级性能,输出中会显示Function: d at line 16(对应代码中d函数的行号),而非包装器wrapper。
如果多个函数共用同一装饰器,每个被包装函数的__wrapped__属性都指向各自的原始函数,这样就能得到每个目标函数的独立分析结果,不会出现包装器的全局统计数据。
内容的提问来源于stack exchange,提问作者Vulpo
相关产品推荐
相关产品推荐

