I have written a library for this sort of thing, which I've just put on GitHub in case it is useful to anybody.
It works by wrapping functions, classes or objects with a proxy which logs every interaction. This includes not just the names of the methods, but also their arguments and return values, and which methods called which other methods (in a tree).
Usage:
from tracer import tracer
@tracer
class classname(object):
def __init__(self):
self.hold = None
def funcname(self):
self.hold = 'a'
return self
def method(self, c):
self.hold = self.hold * c
return self
def recursive_method(self, n):
if n > 0:
self.recursive_method(n - 1)
self.recursive_method(n - 2)
c = classname().funcname().method(10)
c.recursive_method(3)
c.print_call_tree()
Output:
* +-> __init__()
|
+-> funcname() +-> <__main__.classname object at 0x0000000002A9EBA8>
|
+-> method(10) +-> <__main__.classname object at 0x0000000002AE2160>
|
+-> recursive_method(3) +-> recursive_method(2) +-> recursive_method(1) +-> recursive_method(0)
| | |
| | +-> recursive_method(-1)
| |
| +-> recursive_method(0)
|
+-> recursive_method(1) +-> recursive_method(0)
|
+-> recursive_method(-1)
Fair warning: it is a bit brittle, for example you can see the log shows different ids for the object returned by funcname
and method
, even though these should be the same object with the same id.