1import sys 2 3try: 4 sys.settrace 5except AttributeError: 6 print("SKIP") 7 raise SystemExit 8 9 10def print_stacktrace(frame, level=0): 11 # Ignore CPython specific helpers. 12 if frame.f_globals["__name__"].find("importlib") != -1: 13 print_stacktrace(frame.f_back, level) 14 return 15 16 print( 17 "%2d: %s@%s:%s => %s:%d" 18 % ( 19 level, 20 " ", 21 frame.f_globals["__name__"], 22 frame.f_code.co_name, 23 # Keep just the filename. 24 "sys_settrace_" + frame.f_code.co_filename.split("sys_settrace_")[-1], 25 frame.f_lineno, 26 ) 27 ) 28 29 if frame.f_back: 30 print_stacktrace(frame.f_back, level + 1) 31 32 33class _Prof: 34 trace_count = 0 35 36 def trace_tick(self, frame, event, arg): 37 self.trace_count += 1 38 print_stacktrace(frame) 39 40 41__prof__ = _Prof() 42 43alice_handler_set = False 44 45 46def trace_tick_handler_alice(frame, event, arg): 47 print("### trace_handler::Alice event:", event) 48 __prof__.trace_tick(frame, event, arg) 49 return trace_tick_handler_alice 50 51 52bob_handler_set = False 53 54 55def trace_tick_handler_bob(frame, event, arg): 56 print("### trace_handler::Bob event:", event) 57 __prof__.trace_tick(frame, event, arg) 58 return trace_tick_handler_bob 59 60 61def trace_tick_handler(frame, event, arg): 62 # Ignore CPython specific helpers. 63 to_ignore = ["importlib", "zipimport", "encodings"] 64 frame_name = frame.f_globals["__name__"] 65 if any(name in frame_name for name in to_ignore): 66 return 67 68 print("### trace_handler::main event:", event) 69 __prof__.trace_tick(frame, event, arg) 70 71 if frame.f_code.co_name != "factorial": 72 return trace_tick_handler 73 74 global alice_handler_set 75 if event == "call" and not alice_handler_set: 76 alice_handler_set = True 77 return trace_tick_handler_alice 78 79 global bob_handler_set 80 if event == "call" and not bob_handler_set: 81 bob_handler_set = True 82 return trace_tick_handler_bob 83 84 return trace_tick_handler 85 86 87def factorial(n): 88 if n == 0: 89 return 1 90 else: 91 return n * factorial(n - 1) 92 93 94def do_tests(): 95 # These commands are here to demonstrate some execution being traced. 96 print("Who loves the sun?") 97 print("Not every-", factorial(3)) 98 99 from sys_settrace_subdir import sys_settrace_generic 100 101 sys_settrace_generic.run_tests() 102 return 103 104 105sys.settrace(trace_tick_handler) 106do_tests() 107sys.settrace(None) 108 109print("\n------------------ script exited ------------------") 110print("Total traces executed: ", __prof__.trace_count) 111