from sys import settrace, stderr from dis import disassemble, get_instructions def gtrace(g_frame, g_event, g_arg): code = g_frame.f_code name = code.co_name insts = list(get_instructions(code)) print(f'gtrace: {g_event}: {name}', file=stderr) 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] print(f'ltrace: {event}: {name}:{line}: {prev_off} -> {offset}: {inst.opname} {inst.argrepr}') prev_off = offset return ltrace return ltrace settrace(gtrace, 1) def f(): print("f") g() 1//0 # test raise tracing. def g(): print("g") try: f() except ZeroDivisionError as e: print('top-level exception:', e)