为何局部trace函数会为函数调用生成line事件?
Python函数追踪:调用子函数时先触发line事件的原因
先拿最常见的追踪示例代码来说明你的场景(和你遇到的逻辑一致):
import sys def trace_calls(frame, event, arg): if event == 'call': print(f"全局trace - call: {frame.f_code.co_name}") return trace_lines # 返回局部trace函数,处理后续line事件 def trace_lines(frame, event, arg): if event == 'line': print(f"局部trace - line: {frame.f_code.co_name}, line {frame.f_lineno}") return trace_lines sys.settrace(trace_calls) def c(): pass def b(): c() # 触发疑问的关键行 b()
运行后输出大概是:
全局trace - call: b 局部trace - line: b, line 18 全局trace - call: c 局部trace - line: c, line 15
输出详细拆解
全局trace - call: b:调用b()时,Python触发全局trace的call事件,打印函数名,同时返回trace_lines作为b的局部trace处理器。局部trace - line: b, line 18:b函数执行到c()这一行——这行代码属于b的函数体,Python执行任何一行函数内代码前,都会触发当前函数的局部trace的line事件,所以先打印这一条。全局trace - call: c:处理c()的调用动作时,Python进入新函数c,触发全局trace的call事件,同时为c绑定trace_lines作为局部trace。局部trace - line: c, line 15:c函数执行到自身的pass语句,触发它的局部trace的line事件。
现象核心原因
line事件是绑定到当前正在执行的函数的:只要代码走到某个函数体的某一行,就会触发该函数局部trace的line事件。- 调用子函数的语句本身是父函数的一行代码,所以父函数的
line事件必然先触发,之后才会执行子函数的调用逻辑,进而触发子函数的call事件。 - 全局trace的
call事件仅在进入新函数上下文时触发,和父函数当前行的执行流程是两个独立的阶段,父函数的行执行优先于子函数的调用触发。
内容的提问来源于stack exchange,提问作者xscorp7
相关产品推荐
相关产品推荐

