在 Python 3.7 中,来自 sys.settrace 的 'opcode' 事件是否提供了有关字节码本身的任何信息?

In Python 3.7, does the 'opcode' event from sys.settrace give any information about the bytecode itself?

所以我正在玩 sys.settrace 函数。在 Python 3.7 中,添加了一个新的 opcode 事件

'opcode'
The interpreter is about to execute a new opcode (see dis for opcode details). The local trace function is called; arg is None; the return value specifies the new local trace function. Per-opcode events are not emitted by default: they must be explicitly requested by setting f_trace_opcodes to True on the frame.

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

这个事件是不是只带来了更细的粒度,没有给出任何额外的信息?

如果您需要更多信息,您将需要检查传递给跟踪函数的 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()