Linux、Mac和Windows的硬递归限制是多少?

37

Python的sys模块提供了一个函数setrecursionlimit,可以让您更改Python的最大递归深度限制。文档中说:

最高可能限制取决于平台。

我的问题是:在CPython下,各个平台的最高可能限制是多少?我想知道Linux、Mac和Windows的值。

更新:我们能否避免“你做错了”的答案?我知道尝试进行非常深的递归通常不是一个好主意。我已经考虑了在我具体情况下的利弊,并决定要这样做。


2
这不也取决于你有多少内存等等吗? - Justin
可能相当于“{os}上最大可能的setrlimit堆栈大小是多少”。对于Linux来说,我打赌几乎所有用户空间RAM都可以使用,但我不确定。该值可以通过resource.setrlimit进行操作:https://dev59.com/6G445IYBdhLWcg3wDWCc - Ciro Santilli OurBigBook.com
2个回答

36

在Windows平台上(至少如此),sys.setrecursionlimit并不是全部的解决方案。每个线程都有一个递归深度的硬限制,当达到一定限制时需要调用 threading.stack_size 并创建一个新线程。 (我认为是1MB,但不确定)我使用这种方法将递归深度增加到64MB。

import sys
import threading

threading.stack_size(67108864) # 64MB stack
sys.setrecursionlimit(2 ** 20) # something real big
                               # you actually hit the 64MB limit first
                               # going by other answers, could just use 2**32-1

# only new threads get the redefined stack size
thread = threading.Thread(target=main)
thread.start()
我没有尝试过查看threading.stack_size可能存在的限制,但可以自由地尝试...那是你需要查看的地方。
总之,sys.setrecursionlimit只是解释器本身强制执行的限制。 threading.stack_size允许您操纵操作系统强制执行的实际限制。如果首先达到后者的限制,Python将完全崩溃。

如果我没有'main'对象,那么在'target=main'的位置应该放什么? - mmj
你可以在那里放任何函数名。它不一定要叫做main。 - FogleBird
无论我将堆栈大小设置为多少,都无法解决递归限制问题。我知道我需要的真正递归深度在100k以下,并且我设法在Linux下运行它,但在Windows下无法运行。 - mmj
在我的Windows 10创作者更新版本上完美运行。我可以通过这种方式增加堆栈大小,最多可达2^28-1字节(或256 MB);不确定默认值是多少,但肯定远远小于这个值。为什么不能超过256MB?也许是一些Windows的限制? - max
在macOS 10.14.5上存在相同的问题,只有这个解决方案有效!感谢您拯救了我的整个糟糕的一天! - Mr. Sun Lin

3

在CPython中不应过度使用递归调用。它没有尾部优化,函数调用占用了大量内存和处理时间。这些限制可能不适用于其他实现,这并不是蓝图计划。

在CPython中,递归对于遍历数据结构很好(其中1000个限制对于所有人都足够),但对于算法不是很好。如果我要实现与图相关的算法并达到递归限制,我会实现自己的堆栈并使用迭代,或者在手动提高限制之前搜索以C/C++/任何语言实现的库。


13
谢谢您提供的信息,但这更像是一条有见地的评论,而不是一个回答。作为一个回答,它属于“你做错了”的类型。 - Ram Rachum
谢谢@Xavier。事实上,在这个行业里,我从别人那里学到的几乎所有东西都是“你做错了”的变体。 - Marco Mariani
1
我完全同意你的观点。你不需要递归,也不需要堆栈限制。如果你导致了堆栈溢出,那么你的方法是错误的。=P - Xavier Ho

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接