如何在包装函数上使用 line_profiler?

问题描述 投票:0回答:2

我一直在尝试在包装函数上使用

line_profiler
。但是,分析的是包装器函数而不是包装函数。下面的可执行代码片段显示我可以看到我的
@decorate
包装函数而不是我的
d()
函数被分析。

片段:testy_profiler.py

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)
lp_wrapper = lprofiler(go)
lp_wrapper()
lprofiler.print_stats()

输出:

$ python test_profiler.py
a
d
decorating
Timer unit: 1e-07 s

Total time: 1e-05 s
File: C:\Users\RENARDCH\Workspace\testy_profiler\test_profiler.py
Function: a at line 3

Line #      Hits         Time  Per Hit   % Time  Line Contents
==============================================================
     3                                           def a():
     4         1        100.0    100.0    100.0      print("a")

Total time: 4.4e-06 s
File: C:\Users\RENARDCH\Workspace\testy_profiler\test_profiler.py
Function: wrapper at line 8

Line #      Hits         Time  Per Hit   % Time  Line Contents
==============================================================
     8                                                  @wraps(func)
     9                                                  def wrapper(*args, **kwargs):
    10         1         24.0     24.0     54.5                 r = func(*args, **kwargs)
    11         1         18.0     18.0     40.9                 print("decorating")
    12         1          2.0      2.0      4.5                 return r

Total time: 1.87e-05 s
File: C:\Users\RENARDCH\Workspace\testy_profiler\test_profiler.py
Function: go at line 19

Line #      Hits         Time  Per Hit   % Time  Line Contents
==============================================================
    19                                           def go():
    20         1        126.0    126.0     67.4      a()
    21         1         61.0     61.0     32.6      d()

当两个函数用同一个包装器包装时,这尤其会带来问题,因为将为包装器生成全局分析,而不是单独为每个函数生成分析。

line_profiler
版本是
3.4.0

python wrapper line-profiler
2个回答
2
投票

根据这个问题,行分析器不会分析装饰函数内的代码,而是分析装饰器。

但是,有一个解决方法。

如果你想分析装饰器调用的函数,你可以这样做:

lprofiler.add_function(d.__wrapped__)

由于您使用的是

functool.wraps()
,因此将
__wrapped__
属性设置为指向原始函数。许多其他 Python 装饰器也设置了
__wrapped__
,尽管这不是必需的。更多关于
__wrapped__
的信息可以在这里找到。


1
投票

绕过是让

d()
调用一个非包装函数,实际上完成这项工作,并分析这个子函数而不是
d()

[...]
@decorate
def d():
    effective_d()

def effective_d():
    print("d")

[...]
lprofiler.add_function(effective_d)
[...]
© www.soinside.com 2019 - 2024. All rights reserved.