#!/usr/bin/env python3 from sys import settracestate, gettracestate from dis import disassemble, get_instructions def gtrace(g_frame, g_event, g_arg): code = g_frame.f_code name = code.co_name insts = tuple(get_instructions(code)) print(f'! gtrace: {g_event}: {name}') disassemble(code) if g_event != 'call': return None prev_off = -1 def ltrace(frame, event, arg): nonlocal prev_off assert frame.f_code == code line = frame.f_lineno offset = frame.f_lasti index = offset // 2 # as of python3.6, all instructions are 2 bytes. inst = insts[index] argrepr = inst.argrepr and ' ' + inst.argrepr print(f'! ltrace: {event[:4]}: {name}:{line}: {prev_off} -> {offset}: 0x{inst.opcode:02x} {inst.opname}{argrepr}') prev_off = offset return ltrace return ltrace def example(): try: f() except ZeroDivisionError as e: print('example exception:', e) def f(): print("f") g() 1//0 # test raise tracing. def g(): print("g") settracestate(gtrace, trace_instructions=True) example() print('\n---- test gettracestate ----\n') print('sys.gettracestate:', gettracestate()) settracestate(None) print('sys.gettracestate:', gettracestate())