When debugging it is often immensely helpful to know the exact value of each operand of an operation that is about to take place, but currently even with frame.f_trace_opcodes
enabled all we can get from a trace function set by sys.settrace
is the opcode from frame.f_code.co_code[frame.f_lasti]
, which isn’t very helpful because the opcodes are static for a given code object and what we’re more interested in during debugging are the actual values that an opcode is about to operate on from the interpreter stack.
I think it makes sense to make the values of all relevant operands in the interpreter stack that an opcode is going to process, along with the opcode itself and its argument, available as the arg argument for the trace function, so that it is a tuple like:
opcode, arg, operands
arg
would be None
for opcodes that don’t have an argument. And operands
would be a tuple of relevant values from the bottom to the top of the stack.
So for example, with the following code:
a = 1
[a, 2]
The trace function, as it gets called when the BUILD_LIST
bytecode is about to be executed, shall have its arg argument set to:
47, 2, (1, 2)
where 47 is the opcode of BUILD_LIST
.
Obviously this will add quite a bit of performance overhead to tracing but will help make the f_trace_opcodes
option actually useful. If somehow the current behavior is still preferred we can switch to the new behavior only when f_trace_opcodes
is set to 2 or something other than True
, though I think very few people would be looking for performance when trying to debug at the bytecode level so an option to retain the current behavior may not be necessary.