Overview
Every recursive call consumes real memory on the interpreter's underlying call stack, and Python's recursion limit exists specifically to convert what would otherwise be an uncontrolled crash, exhausting the real C stack the interpreter runs on, into a clean, catchable RecursionError raised well before that happens. The limit is a proxy for a real, platform-dependent constraint, not an arbitrary rule, which is exactly why Python's own documentation warns that raising it "should be done with care": setting it higher than the platform's actual available stack can support doesn't create more stack space, it just removes the early warning, letting recursion run deep enough to genuinely exhaust the stack and crash the process with a low-level segmentation fault instead of the controlled exception the limit was designed to provide.
Quick Reference
| Concept | What it means |
|---|---|
| Call stack | Real memory tracking each active function call's state |
| Recursion limit | A configured ceiling that raises RecursionError before the real stack is exhausted |
| Raising the limit too high | Doesn't add stack space; can let recursion crash the process instead |
| Iterative rewrite | Trades some code clarity for removing recursion-depth risk entirely |
Syntax
import sys
sys.getrecursionlimit() # default is typically 1000
sys.setrecursionlimit(3000) # raise with care - see belowExamples
# Raising the limit doesn't create more real stack space;
# it can convert a clean RecursionError into a process crash.
import sys
sys.setrecursionlimit(1_000_000)
def deep(n):
return 1 if n == 0 else 1 + deep(n - 1)
deep(500_000) # may segfault instead of raising RecursionErrorThe recursion limit protects real stack memory, not an arbitrary count
Python's documentation is explicit: a too-high limit can lead to a crash, because the limit is a proxy for actual, platform-dependent C stack space. Raising it doesn't add capacity, it just delays or removes the clean failure the limit exists to provide.
Visual Diagram
Common Mistakes
- Treating the recursion limit as an arbitrary language restriction rather than a proxy for real, finite stack memory.
- Raising the recursion limit to a very high value to "fix" a
RecursionError, without checking whether the platform's actual stack can support that depth at all. - Writing deeply recursive code for a problem whose depth scales with input size, without considering an iterative rewrite for large or adversarial inputs.
- Assuming a
RecursionErroris always a bug in the recursive logic, rather than sometimes being legitimate depth that needs an iterative approach instead.
Performance
- Each recursive call has real overhead (a new stack frame, argument copying) beyond just the logical work being done, which is part of why very deep recursion can be measurably slower than an equivalent iterative loop.
- An iterative, explicit-stack rewrite removes both the recursion-limit risk and per-call frame overhead, at the cost of the code no longer mirroring the problem's recursive structure as directly.
Best Practices
- Treat the recursion limit as a real constraint tied to actual stack memory, not a number to casually raise away.
- Rewrite recursion iteratively when depth scales with input size in a way that could plausibly exceed a platform's real stack capacity.
- Test any raised recursion limit on the actual target platform, since safe values are platform-dependent, not portable.
- Prefer recursion for problems where it genuinely mirrors the structure (trees, divide-and-conquer) and depth is naturally bounded small, reserve iteration for open-ended depth.