Python3 has per-statement tracing, but that’s a little too all-or-nothing for me. Every other tracer I found on the web was vastly overengineered, so I hacked this decorator together this afternoon:
import inspect
trace_indent = 0
def tracing(f):
sig = inspect.signature(f)
def do_it(*args, **kwargs):
global trace_indent
ws = ' ' * (trace_indent * 2)
print("%sENTER %s: " % (ws, f.__name__))
for ix, param in enumerate(sig.parameters.values()):
print("%s %s: %s" % (ws, param.name, args[ix]))
trace_indent += 1
result = f(*args, **kwargs)
trace_indent -= 1
print("%sEXIT %s (returned %s)" % (ws, f.__name__, result))
return result
return do_it
Then, for this program,
@tracing
def fib(n):
if n == 0:
return 0
elif n == 1:
return 1
else:
return fib(n-1) + fib(n-2)
if __name__ == '__main__':
print(fib(5))
You get this:
$ python3 tracing_test.py
ENTER fib:
n: 5
ENTER fib:
n: 4
ENTER fib:
n: 3
ENTER fib:
n: 2
ENTER fib:
n: 1
EXIT fib (returned 1)
ENTER fib:
n: 0
EXIT fib (returned 0)
EXIT fib (returned 1)
ENTER fib:
n: 1
EXIT fib (returned 1)
EXIT fib (returned 2)
ENTER fib:
n: 2
ENTER fib:
n: 1
EXIT fib (returned 1)
ENTER fib:
n: 0
EXIT fib (returned 0)
EXIT fib (returned 1)
EXIT fib (returned 3)
ENTER fib:
n: 3
ENTER fib:
n: 2
ENTER fib:
n: 1
EXIT fib (returned 1)
ENTER fib:
n: 0
EXIT fib (returned 0)
EXIT fib (returned 1)
ENTER fib:
n: 1
EXIT fib (returned 1)
EXIT fib (returned 2)
EXIT fib (returned 5)
5
(MIT license, because why not.)