What is the maximum recursion depth in Python, and how to increase it?
It is a guard against a stack overflow, yes. Python (or rather, the CPython implementation) doesn't optimize tail recursion, and unbridled recursion causes stack overflows. You can check the recursion limit with sys.getrecursionlimit
:
import sys
print(sys.getrecursionlimit())
and change the recursion limit with sys.setrecursionlimit
:
sys.setrecursionlimit(1500)
but doing so is dangerous -- the standard limit is a little conservative, but Python stackframes can be quite big.
Python isn't a functional language and tail recursion is not a particularly efficient technique. Rewriting the algorithm iteratively, if possible, is generally a better idea.
RecursionError: maximum recursion depth exceeded while calling a Python object. python error
if the_list
is of length 1 (which will happen at some stage in your recursive calls) you will end up in an infinite recursion... (mid
will be 0
).
you need to address that as well as a base case:
def sum_list(the_list):
if not the_list:
return 0
if len(the_list) == 1:
return the_list[0]
else:
mid = len(the_list) // 2
return sum_list(the_list[:mid]) + sum_list(the_list[mid:])
i assume this is an exercise in recursion. python offers sum
to do that efficiently.
Databricks Exception: ERROR: maximum recursion depth exceeded in comparison
Error - Exception: ERROR: maximum recursion depth exceeded in
comparison
This error is related to Recursion Depth Limit in Python.
This error says it all—maximum recursion depth exceeded in comparison. This tells you that Python’s recursion depth limit of 1000 is reached.
A recursive function could call itself indefinitely. In other words, you could end up with an endless loop.
Also, a stack overflow error can occur even if the recursion is not infinite. This can happen due to too big of a stack frame.
In Python, the recursion depth limit takes these risks out of the equation.
Python uses a maximum recursion depth of 1000 to ensure no stack overflow errors and infinite recursions are possible.
This recursion limit is somewhat conservative, but it is reasonable as stack frames can become big in Python.
How to Change the Recursion Depth Limit in Python
import sys
print(sys.setrecursionlimit(2000))
For more information follow this article by Artturi Jalli
RecursionError: maximum recursion depth exceeded in comparison
When a RecursionError
is raised, the python interpreter may also offer you the context of the call that caused the error. This only serves for debugging, to give you a hint where in your code you should look in order to fix the problem.
See for example this circular str
-call setup that leads to a different message:
>>> class A:
... def __str__(self):
... return str(self.parent)
>>> a = A()
>>> a.parent = a
>>> str(a)
RecursionError: maximum recursion depth exceeded while calling a Python object
There is no documentation of this behaviour on the issue discussion where RecursionError
was introduced, but you can just search the cpython code for occurences of Py_EnterRecursiveCall. Then you can see the actual contexts that will be returned depending on where the error is raised:
Py_EnterRecursiveCall(" while encoding a JSON object")
Py_EnterRecursiveCall(" while pickling an object")
Py_EnterRecursiveCall(" in __instancecheck__")
Py_EnterRecursiveCall(" in __subclasscheck__")
Py_EnterRecursiveCall(" in comparison")
Py_EnterRecursiveCall(" while getting the repr of an object")
Py_EnterRecursiveCall(" while getting the str of an object")
Py_EnterRecursiveCall(" while calling a Python object")
Py_EnterRecursiveCall("while processing _as_parameter_") # sic
# .. and some more that I might have missed
What is the maximum recursion depth in Python, and how to increase it?
It is a guard against a stack overflow, yes. Python (or rather, the CPython implementation) doesn't optimize tail recursion, and unbridled recursion causes stack overflows. You can check the recursion limit with sys.getrecursionlimit
:
import sys
print(sys.getrecursionlimit())
and change the recursion limit with sys.setrecursionlimit
:
sys.setrecursionlimit(1500)
but doing so is dangerous -- the standard limit is a little conservative, but Python stackframes can be quite big.
Python isn't a functional language and tail recursion is not a particularly efficient technique. Rewriting the algorithm iteratively, if possible, is generally a better idea.
Maximum recursion depth exceeded when finding the depth of binary-search-tree
The recursion depth should not be that great on the condition that your binary tree is relatively balanced. Still, even when your binary tree is degenerate, like is what happens when you create it from a sorted sequence (sorted
) then you should still only need O(n) stack space.
But your code for both bst_build
and find_depth
needs a lot more stack space. This is because they don't backtrack when reaching a leaf. Instead they both restart a traversal from the root, without getting out of the current recursion tree first:
bst_build
does this by callingbst_build
again when it wants to insert the next input fromseq
. This should happen in a loop (outside of recursion), not when you are already deep in a recursion tree.find_depth
does this by callingfind_depth
again when it reaches a leaf. This should happen by first backtracking one step and then recurring again into a sibling node. Instead it restarts the search from the root (which is a waste of time), and does so without getting out of recursion first.
This makes this code need a tremendous amount of stack space, which will be like O(n²) in the worst (degenerate) case.
Not related to your question, but it is a pity -- and completely unnecessary -- that find_depth
destroys the tree as it is being traversed.
Another problem that is not related to your question: your bst_check
is not correct. It will return True for the following tree:
2
/
1
\
3
Yet, this tree is not a valid BST. The requirement for a valid BST is not only that a left child is less than its parent, but that all nodes in the left subtree are less than that parent.
Here is a fix for all these issues:
def bst_build(seq):
if not seq:
return None
def add_child(main, value):
if value == main[0]:
return
childindex = 1 if main[0] > value else 2
if not main[childindex]:
main[childindex] = [value, None, None]
else:
add_child(main[childindex], value)
binary_search_tree = [seq[0], None, None]
for value in seq[1:]:
add_child(binary_search_tree, value)
return binary_search_tree
def bst_depth(b):
return 1 + max(bst_depth(b[1]) if b[1] else -1, bst_depth(b[2]) if b[2] else -1)
def bst_check(b, low=float("-inf"), high=float("inf")):
return not b or (low <= b[0] <= high and bst_check(b[1], low, b[0])
and bst_check(b[2], b[0], high))
Segmentation fault: 11 / RecursionError: maximum recursion depth exceeded while calling a Python object
Method 1
The issue lies in the recursive calls:
elif target < l[midpoint]:
return binary_search(l, target,low = None, high = midpoint - 1)
else:
# target > l[midpoint]
return binary_search(l, target, low = midpoint + 1, high = None)
You want to copy the low
, and high
rather than setting them to None
. The correct call should be:
elif target < l[midpoint]:
return binary_search(l, target,low = low, high = midpoint - 1)
else:
# target > l[midpoint]
return binary_search(l, target, low = midpoint + 1, high = high)
To demonstrate the bug:
Using your example, in the original call: low=0, high=8
Then, in the 1st recursion, low=0, high=4
.
Now, target=10 > midpoint=5
, you code makes the following call
binary_search(l, target, low = midpoint + 1, high = None)
Since high=None
, it will be set to high=8
in the next recursion, giving you low=3, high=8
. This is not what you want, since you already eliminated the top half. So you need to carry over low
and high
in the recursive call rather than setting them to None
.
To be more efficient, you can also check l[low]
and l[high]
in addition to l[midpoint]
against the target.
Method 2
Alternatively, you can give a subset of the list in the recursive call. Then, you don't really need the low
and high
argument any more. Since slicing only generate new references rather than copies, it doesn't have too much impact on memory.
elif target < l[midpoint]:
return binary_search(l[low:midpoint], target,low = None, high = None)
else:
# target > l[midpoint]
return binary_search(l[midpoint+1:high+1], target, low = None, high = None)
Related Topics
Size Legend for Plotly Bubble Map/Chart
How to Use Rpy2 to Save a Pandas Dataframe to an .Rdata File
Interpreting a Benchmark in C, Clojure, Python, Ruby, Scala and Others
Python VS Groovy VS Ruby? (Based on Criteria Listed in Question)
How to Integrate a Standalone Python Script into a Rails Application
Integration Testing for a Web App
How to Write a Perl, Python, or Ruby Program to Change the Memory of Another Process on Windows
Convert Backward Slash to Forward Slash in Python
What's the Ruby Equivalent of Python's Os.Walk
Restrictons of Python Compared to Ruby: Lambda'S
Efficient Ways to Duplicate Array/List in Python
Python Equivalent of Ruby's Each_Slice(Count)
Is There an R Equivalent of the Pythonic "If _Name_ == "_Main_": Main()"
Calling the "Source" Command from Subprocess.Popen
What's the Best Way to Return Multiple Values from a Function