2

所以我在玩这个sys.settrace功能。在 Python 3.7 中,opcode添加了一个新事件

'opcode'
解释器即将执行一个新的操作码(参见 dis 了解操作码的详细信息)。调用本地跟踪函数;arg 是无;返回值指定新的本地跟踪函数。默认情况下不发出每个操作码事件:必须通过f_trace_opcodes在帧上设置为 True 来明确请求它们。

我能够得到那些操作码事件,但似乎没有进一步的信息——我什至不知道操作码是什么,它在做什么。

这个事件是否只带来了更精细的粒度,而没有提供任何额外的信息?

4

1 回答 1

2

如果您想了解更多信息,则需要检查frame传递给跟踪函数的参数。特别是,您希望查看frame.f_lasti执行的最后一条指令并frame.f_code.co_code访问该指令。将这两者一起使用将为您提供实际的操作码。如果你想要助记符,那么你会想要使用dis.opname; 但是,如果您只是将它与另一个操作码匹配,那么您可以dis.opmap改用它。以下示例是人为设计的,但它演示了使用刚刚提供的提示可以实现的一些功能:

#! /usr/bin/env python3
import dis
import sys


def main():
    dis.dis(add)
    sys.settrace(get_trace(False, get_callback(celebrate)))
    total = add(1, 2)
    print(f'total = {total}')
    sys.settrace(None)
    total = add(3, 4)
    print(f'total = {total}')
    print('Done')


def get_trace(trace_lines=True, opcode_callback=None):
    trace_opcodes = callable(opcode_callback)

    # noinspection PyUnusedLocal
    def trace(frame, event, arg):
        frame.f_trace_lines = trace_lines
        frame.f_trace_opcodes = trace_opcodes
        if trace_opcodes and event == 'opcode':
            opcode = frame.f_code.co_code[frame.f_lasti]
            opname = dis.opname[opcode]
            opcode_callback(frame, opcode, opname)
        return trace

    return trace


def get_callback(return_handler=None):
    handle_return = callable(return_handler)

    def echo_opcode(frame, opcode, opname):
        print(f'# {opname} ({opcode}) #')
        if handle_return and opcode == dis.opmap['RETURN_VALUE']:
            return_handler(frame)

    return echo_opcode


# noinspection PyUnusedLocal
def celebrate(frame):
    print('/-------------------\\')
    print('| We are returning! |')
    print('\\-------------------/')


def add(a, b):
    return a + b


if __name__ == '__main__':
    main()
于 2019-05-15T01:59:06.153 回答