Description
Before PEP 669, the opcode trace is togglable after trace function being set. So something like
import sys
def opcode_trace_func(frame, event, arg):
print(frame, event)
return opcode_trace_func
sys.settrace(opcode_trace_func)
sys._getframe().f_trace = opcode_trace_func
sys._getframe().f_trace_opcodes = True
def f():
a = [1, 2, 3]
return a[0]
f()
would work.
After PEP 669, the opcode event is set on sys.settrace()
so it's impossible to enable it after enabling the trace.
sys._getframe().f_trace_opcodes = True
sys.settrace(opcode_trace_func)
sys._getframe().f_trace = opcode_trace_func
kind of works but it's super intuitive.
For the current implementation, if we enabled opcode before we do sys.settrace()
, it would be "enabled" forever. Meaning the event will be always on, the callback will be always triggered, but frame.f_trace_opcode
will be checked in the callback function. Can we always have opcode callback on? It would be a performance hit(extra call for each opcode), but that happens if we want any opcode event at all, and I think that's basically how the old tracing system does it.
Another option would be making f_trace_opcode
a descriptor and toggle(actually, probable just enable) opcode events there.
If we don't want to do that at all and just want to break the backward-compatibility because no one is doing insturction trace anyway (I only realized this when syncing #103050 to the lastest change), we should probably document it - make sure the current frame's f_trace_opcode
is set before calling sys.settrace()
if you want opcode events.
BTW we would've caught this if we already had the instruction level debugging :)