python internals查询。请问大师请帮助我理解为什么下面的代码会导致“致命的python错误”,而不是很好地捕捉到递归限制溢出?
hasMany
用例如:
来称呼它def flowfunc(x):
try:
if x < 0:
flowfunc(x + 3)
flowfunc(x + 5)
else:
flowfunc(x - 1)
except:
print("exception at: x = ", x)
所有突破损失
flowfunc(0)
似乎这一切都取决于第二次递归调用。以下代码表现良好:
exception at: x = -1
Fatal Python error: Cannot recover from stack overflow.
...
...
[threads data...]
与
def flowfunc2(x):
try:
if x < 0:
flowfunc2(x + 3)
# flowfunc2(x + 5)
else:
flowfunc2(x - 1)
except:
print("exception at: x = ", x)
返回(值可能会根据可用的堆栈深度而改变):
flowfunc2(0)
我在python 3.6上。您的见解将受到赞赏。
答案 0 :(得分:0)
在正面和负面之间有一个振荡的递归函数,从未真正终止。一旦达到Python设置的最大递归深度,就会捕获异常,打印当前值。
在第一个版本中(你得到了致命的错误),在打印出最大深度达到异常后,而不是清理你的调用堆栈,你只需要升级一个并调用flowfunc(x + 5)
堆积更多调用堆栈中的调用比Python可能处理的调用。那就是你得到致命错误的地方。在第二个版本中,在打印异常之后,您只需直接将None返回给原始调用者并终止程序的执行。在某种程度上,第二个代码段中的异常打印用作递归的base case
,因为在调用者中没有其他任何操作,因此您的程序会正常终止。
所以是的,你的观察是正确的,它取决于第二次递归调用。
答案 1 :(得分:0)
这与https://bugs.python.org/issue6028的错误相同。
原因也在那里解释: “实际上,这是正常行为。但是,引发了RuntimeError 你在except子句中捕获它,然后无限地再次递归。 解释器意识到它“无法从堆栈溢出中恢复”, 正如消息所说,然后纾困。“
基本上,由于存在第二次递归调用,程序会在第一次错误被捕获后继续,并且它会保持分支并生成无限的RuntimeError。