Python has a built-in API for tracing: https://docs.python.org/3/library/sys.html#sys.settrace
Here's an example of how to use it (obviously a minimal case, you can customise your handler do do whatever you need):
def mytrace(frame, event, arg):
if event == "call":
print("call", frame.f_code.co_name, frame.f_locals)
elif event == "return":
print("return", frame.f_code.co_name, arg)
return mytrace
import sys
sys.settrace(mytrace)
For example, given the following code: def three(z):
return 3
def two(y):
return three("BBB") - 1
def one():
return two("AAA") - 1
one()
It will output: call one {}
call two {'y': 'AAA'}
call three {'z': 'BBB'}
return three 3
return two 2
return one 1