在 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()
所以我正在玩 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 settingf_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()