I have 2 solutions to a recursion problem that I need for a function (actually a method). I want it to be recursive, but I want to set the recursion limit to 10 and reset it after the function is called (or not mess with recursion limit at all). Can anyone think of a better way to do this or recommend using one over the others? I'm leaning towards the context manager because it keeps my code cleaner and no setting the tracebacklimit, but there might be caveats?
import sys
def func(i=1):
print i
if i > 10:
import sys
sys.tracebacklimit = 1
raise ValueError("Recursion Limit")
i += 1
func(i)
class recursion_limit(object):
def __init__(self, val):
self.val = val
self.old_val = sys.getrecursionlimit()
def __enter__(self):
sys.setrecursionlimit(self.val)
def __exit__(self, *args):
sys.setrecursionlimit(self.old_val)
raise ValueError("Recursion Limit")
def func2(i=1):
"""
Call as
with recursion_limit(12):
func2()
"""
print i
i += 1
func2(i)
if __name__ == "__main__":
# print 'Running func1'
# func()
with recursion_limit(12):
func2()
I do see some odd behavior though with the context manager. If I put in main
with recursion_limit(12):
func2()
It prints 1 to 10. If I do the same from the interpreter it prints 1 to 11. I assume there is something going on under the hood when I import things?
EDIT: For posterity this is what I have come up with for a function that knows its call depth. I doubt I'd use it in any production code, but it gets the job done.
import sys
import inspect
class KeepTrack(object):
def __init__(self):
self.calldepth = sys.maxint
def func(self):
zero = len(inspect.stack())
if zero < self.calldepth:
self.calldepth = zero
i = len(inspect.stack())
print i - self.calldepth
if i - self.calldepth < 9:
self.func()
keeping_track = KeepTrack()
keeping_track.func()
for _ in xrange(N)to do something N times? Is conceptually simpler than abusing aRuntimeError, allows calling other functions without exiting prematurely (or, worse, requiring the caller to take care of that), and should be more efficient as a bonus.