Use traceback for this:
>>> import traceback >>> def f(depth=0): ... print depth, traceback.print_stack() ... if depth < 2: ... f(depth + 1) ... >>> f() 0 File "<stdin>", line 1, in <module> File "<stdin>", line 2, in f None 1 File "<stdin>", line 1, in <module> File "<stdin>", line 4, in f File "<stdin>", line 2, in f None 2 File "<stdin>", line 1, in <module> File "<stdin>", line 4, in f File "<stdin>", line 4, in f File "<stdin>", line 2, in f None
So, if any entry on the stack indicates that the code was called from f , the call was (in) directly recursive. The traceback.extract_stack method gives you easy access to this data. The if len(l[2] ... operator if len(l[2] ... in the example below simply counts the number of exact matches of the function name. To make it even more beautiful (thanks to agf for the idea), you can make it in the decorator:
>>> def norecurse(f): ... def func(*args, **kwargs): ... if len([l[2] for l in traceback.extract_stack() if l[2] == f.func_name]) > 0: ... raise Exception, 'Recursed' ... return f(*args, **kwargs) ... return func ... >>> @norecurse ... def foo(depth=0): ... print depth ... foo(depth + 1) ... >>> foo() 0 Traceback (most recent call last): File "<stdin>", line 1, in <module> File "<stdin>", line 5, in func File "<stdin>", line 4, in foo File "<stdin>", line 5, in func Exception: Recursed
source share