set_trace()
函数用于实现 debugger、profiler、coverage 工具等。它的行为是实现平台的一部分,而不是语言定义的一部分,因此不一定在所有 Python 实现中都可用。
sys.settrace()
用于设置系统的追踪函数。追踪函数是线程特定的;因此对于支持多线程的调试器,必须使用 set_trace()
或 threading.settrace()
给每个正在调试的线程注册追踪函数。
追踪函数应该带三个参数:
frame:当前桢
event:
arg:依赖 event 类型
当进入到新的本地作用域时,追踪函数会被调用(event 参数会被设置为 'call');它应该返回用于这个新作用域的本地追踪函数的引用,如果不追踪该作用域应该返回 None。
本地追踪函数应该返回它自己或其它追踪函数的引用,或者返回 None,以关闭追踪。
如果追踪函数中发生任何错误,它会被取消。
event 的含义如下:
'call'
当函数被调用(或进入其它语句块)时,全局追踪函数会被调用;arg 是 None;返回值用于指定本地追踪函数
'line'
当解释器将要执行新的代码行,或重新执行循环的条件时,本地追踪函数会被调用;arg 是 None;返回值用于指定新的本地追踪函数。对于一个 frame 而言,通过设置它的 f_trace_lines
为 False的方式,禁用 line 事件
'return'
当函数(或其它代码块)将要返回时,本地追踪函数会被调用;arg 是将要被返回的值,如果该事件因程序抛出异常而导致,那么 arg 是 None。追踪函数的返回值会被忽略
'exception'
当发生异常时,本地追踪函数会被调用;arg 是元组 (exception, value, traceback);返回值用于指定新的本地追踪函数
'opcode'
当解释器将要执行新的 opcode 时,本地追踪函数会被调用;arg 是 None;返回值用于指定新的本地追踪函数。默认情况下,opcode 事件不会被发出:可以通过将 frame 的 f_trace_opcodes
设置为 True 的方式,显式地开启
注意:因为异常会沿着调用链传播,因此在每个层级都会生成 'exception' 事件。
可以通过显式地指定 frame.f_trace = tracefunc
的方式,设置追踪函数,而不是依赖已经安装的追踪函数的返回值间接地设置。这种情况,需要在当前 frame 上激活追踪函数,而 settrace()
不需要。为了使这种方式生效,需要使用 settrace()
安装全局的追踪函数,以开启运行时追踪机制。
关于 code 和 frame 对象的更多信息,请参考:https://docs.python.org/3/reference/datamodel.html#types。
import sys
def print_code_object(frame):
for attr in dir(frame.f_code):
if not attr.startswith("co_"):
continue
print(f"attr is {attr}, value is {getattr(frame.f_code, attr)}")
def local_trace_function(frame, event, arg):
print(f"frame is {frame}, event is {event}, arg is {arg}")
# print_code_object(frame)
def global_trace_function(frame, event, arg):
# 启用 opcode 事件
frame.f_trace_opcodes = True
frame.f_trace = local_trace_function
def test1(a):
print(a)
def test2():
return 1
if __name__ == "__main__":
sys.settrace(global_trace_function)
test1(1)
print(test2())