测试Python的最大递归深度时,为什么会多次出现RuntimeError?

6

我想通过以下代码来实验性地确定Python的最大递归深度:

def recursive(i):
    i = i + 1
    try:
        recursive(i)
    except RuntimeError:
        print 'max depth == %d' % i
        exit(0)

recursive(0)

但是当我运行它时,出现了这个问题:
[ hive ~ ]$ python recursive.py 
max depth == 999
max depth == 998
max depth == 997
max depth == 996
max depth == 995
max depth == 994

当程序遇到第一次 RuntimeError 错误时,为什么它不会立即退出,而是继续运行了5个更多的 recursive() 调用?


1
也许打印异常消息可以给你一些线索。 - Maciej Gol
我能够在Windows上通过命令行重现这个问题 :-) - Abhijit
1
啊,啊!exit()不是sys.exit。它是由site模块设置的可调用的exit() - Martijn Pieters
据我所知,exit是一个内置函数。 - alko
@alko:不是的。它是site模块中的Python函数,旨在用于交互式解释器中。 - Martijn Pieters
显示剩余9条评论
2个回答

7

您正在使用Python site模块设置的exit()函数在交互式解释器中使用。

这是您调用的Python代码,而不是C代码。这会触发递归深度异常处理程序多次,直到您远离堆栈限制。

当您紧贴限制时,尝试调用exit()会失败,因为您达到了堆栈限制。因此,引发RuntimeError,回退到998次调用。在这里,您再次尝试调用exit(),它试图执行一些工作并再次引发RuntimeError,然后回退到另一个级别,以此类推,直到剩下足够的堆栈空间最终在Python函数中调用raise SystemExit()

请改用sys.exit(),以避免向堆栈添加更多压力。

或者,以供将来参考,使用sys.getrecursionlimit()函数直接向Python询问限制是多少。

4

在递归(999)try-except中捕获运行时错误,但由exit(0)重新引发。后者大致相当于raise SystemExit(0)模除一些附加调用,这些调用再次造成RuntimeError,请参见以下代码:

def recursive(i):
    try:
        i = i + 1
        recursive(i)
    except RuntimeError as exc:
        print 'max depth == %d' % i
        try:
            exit(0)
        except RuntimeError:
            print 'RuntimeError in exit'

recursive(0)

输出

max depth == 999
RuntimeError in exit

因此,在递归(998)等过程中再次捕获了运行时错误,总共捕获了5次,直到堆栈被展开到exit(0)以避免引发运行时错误。


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