0

I was testing stuff when I noticed that python's recursion limit doesn't seem to apply equally to all functions. I'm not sure why or how and couldn't find any documentation explaining this behavior.

Can someone explain this weird behavior to me? Or at least send me in the right direction?

The Code:

import sys
import inspect


LIMIT = sys.getrecursionlimit()

print(f"recursive limit is: {LIMIT}")


def get_max_lvl(lvl=0):
    try:
        return get_max_lvl(lvl=lvl + 1)
    except RecursionError:
        return lvl


def get_max_lvl_inspect(lvl=0):
    try:
        return get_max_lvl_inspect(lvl=lvl + 1)
    except RecursionError:
        print(f"stack level: {len(inspect.stack())}")
        return lvl


def get_max_lvl_other(lvl=0):
    try:
        return get_max_lvl_other(lvl=lvl + 1)
    except RecursionError:
        print("blah")
        return lvl

I ran the following in a shell:

$ python -i rec.py 
recursive limit is: 1000
>>> get_max_lvl()
998
>>> get_max_lvl_inspect()
stack level: 983
981
>>> get_max_lvl_other()
blah
blah
994

And tried it the other way around in case it was due to the order:

$ python -i rec.py 
recursive limit is: 1000
>>> get_max_lvl_other()
blah
blah
994
>>> get_max_lvl_inspect()
stack level: 983
981
>>> get_max_lvl()
998

But the function outputs seem consistent.

What is going on here?

7
  • If you're getting anywhere near the stack limit you're doing something wrong algorithmically. The actual limit in terms of function calls should just be high enough it's not a problem in practical terms, the exact value is largely irrelevant. Anything over 500 levels deep is, from a design perspective, utterly absurd and you should reconsider what you're doing that lead you to that depth. Commented Aug 21, 2023 at 14:51
  • Well my original goal was to make a wrapper that always runs functions at the max recursion depth limit, just for fun. So as you can see we're reaaaaaally far from caring about performance. For now I just want to understand what's going on. Commented Aug 21, 2023 at 14:53
  • 1
    It's not about performance here. Any local variables you create might have an impact on the stack footprint of a recursive call, so you may get slightly different results depending on how you get to that depth. The intent is to have a sufficiently large stack such that you can run most code, but not necessarily all. As well, on Windows the stack is severely restricted compared to other systems.\ Commented Aug 21, 2023 at 14:56
  • 1
    The name getrecursionlimit is misleading. It's not a recursion stack, it's a call stack. All function calls are stacked, not just recursive calls. Commented Aug 21, 2023 at 16:39
  • 1
    It isn't an XY problem as there is no problem. I'm not trying to solve anything, just wanted to have a bit of fun making a function that "runs along the knife edge" as you said :) Commented Sep 23, 2023 at 8:45

1 Answer 1

3

This is because the inspect.stack function, the print function and the len function all add some frames to the call stack, reducing the space available for recursion depth.

So the more you use those functions, the less space can work with.

  1. get_max_lvl: Not calling these functions -> maximum recursion depth
  2. get_max_lvl_other: Just calling print -> recursion depth lower than 1.
  3. get_max_lvl_inspect: calling all three functions -> recursion depth lower than 2.
Sign up to request clarification or add additional context in comments.

3 Comments

Are functions the only objects that add frames to the call stack?
No, in general any operation that involves creating a new scope of execution, context, or behavior can potentially lead to adding frames to the call stack. Ex: with scopes or exception handling try/except
But those functions are only called when you've already reached a recursion error without them. I think it would be good to really explain how they affect this.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.