【问题标题】:How to trace code run in global scope using sys.settrace?如何使用 sys.settrace 跟踪在全局范围内运行的代码?
【发布时间】:2019-05-06 03:59:37
【问题描述】:

假设我有一段这样的代码:

import sys

def printer(frame, event, arg):
    print(frame, event, arg)
    return printer

sys.settrace(printer)
x = 1
sys.settrace(None)

自从

只要进入新的本地范围,就会调用跟踪函数(事件设置为“调用”)

上面的代码什么也没输出。见我之前的question

那么有没有办法在全局范围内跟踪行,比如x = 1

【问题讨论】:

    标签: python


    【解决方案1】:

    sys.settrace 设置全局 跟踪功能。每当输入新的 Python 堆栈帧('call' 事件)时都会调用此跟踪函数,它的返回值是新作用域的 local 跟踪函数。活动堆栈帧的 local 跟踪函数是用于所有其他事件类型的函数。

    您需要设置现有堆栈帧的本地跟踪功能,但设置全局跟踪功能并不能帮助您做到这一点。要设置现有框架的本地跟踪功能,您可以手动分配框架对象的f_trace 属性给您想要的功能。例如,设置当前帧的本地跟踪功能:

    import sys
    sys._getframe().f_trace = whateverfunc
    

    请注意,如果没有全局跟踪函数,则不会调用本地跟踪函数,因此您还需要设置全局跟踪函数。 (这似乎没有记录。)

    您可以结合sys.settrace 和手动f_trace 分配来跟踪新的和现有的堆栈帧;例如,在'return' 事件中,您可以检查要返回的帧的本地跟踪功能,并将该跟踪功能设置为您想要的任何内容。 bdb debugger framework source code 是一个很好的例子,说明了如何使用跟踪函数。

    【讨论】:

    • 谢谢。我用sys._getframe().f_trace = printer 替换sys.settrace(printer),仍然没有输出。我是不是误会了什么?
    • @laike9m:您还必须设置全局跟踪功能。如果没有全局跟踪函数,则不会调用本地跟踪函数。这是 Python 调试支持的奇怪的、未记录的细节之一。
    • 哇,太疯狂了,非常感谢...github.com/python/cpython/blob/…: 这种行为发生在哪里?
    • @laike9m:这是其中的一个重要部分。 sys.settrace implementation 也很重要,尤其是trace_trampoline,它是一个不同于传递给settrace 的Python 级函数的C 级跟踪函数,用于本地和全局跟踪函数调用。 ceval.c 中的 call_trace 的 Ctrl-F-ing 也会出现一堆相关代码。
    猜你喜欢
    • 1970-01-01
    • 2018-04-01
    • 1970-01-01
    • 1970-01-01
    • 2019-01-23
    • 1970-01-01
    • 2019-11-18
    相关资源
    最近更新 更多