Tracing Python
Sometimes it's useful to trace the execution of Python scripts to understand the code flow and exceptions.
# Python code execution tracing
# To start tracing call sys.settrace(trace_call) before your code.
# To stop tracing call sys.settrace(None) after your code.
# To trace a function, use the decorator @trace
import sys, os.path, inspect
def trace_line(frame, event, arg):
if event != 'line':
return
filename = os.path.basename(frame.f_code.co_filename)
line_no = frame.f_lineno
first_line = frame.f_code.co_firstlineno
lines = inspect.getsourcelines(frame)[0]
print(f"* {filename}:{line_no}:{lines[line_no - first_line].rstrip()}")
return
def trace_call(frame, event, arg):
if event != 'call':
return
# Get the source file path of the current script, works better than __file__
src_filename = os.path.basename(inspect.getfile(lambda: None))
co_filename = os.path.basename(frame.f_code.co_filename)
# Trace only the current file and not imported modules
if co_filename != src_filename:
return
line_no = frame.f_lineno
func_name = frame.f_code.co_name
func_args = inspect.getargvalues(frame).locals
print(f"* {co_filename}:{line_no}:{func_name}({func_args})")
return trace_line
def trace(func):
def wrapper(*args, **kwargs):
sys.settrace(trace_call)
result = func(*args, **kwargs)
sys.settrace(None)
return result
return wrapperTODO
- Trace exceptions