【问题标题】:Fatal Python error: Cannot recover from stack overflow致命的 Python 错误:无法从堆栈溢出中恢复
【发布时间】:2018-11-03 15:17:02
【问题描述】:

我在互联网上阅读了类似的问题,但没有一个答案可以帮助我。我有一个函数,它为每一行数据(数据大约有 2'000'000 行)做一些事情,然后根据它所做的事情用不同的参数调用相同的函数。问题是,过了一会儿我在终端中收到此错误:'致命的 Python 错误:无法从堆栈溢出中恢复。'

似乎导致此错误的最常见错误是无限循环,但我控制并没有无限循环。因此,对我来说,'sys.getrecursionlimit()' 设置为 3000 的问题,这意味着在调用同一函数 3000 次后,它会给我错误。

首先,我不明白“致命 Python 错误:无法从堆栈溢出中恢复”之间的区别。在终端中,或 jupyternotebook 中的“RecursionError:比较中超出最大递归深度”。事实上,对我来说,它可能来自同一个错误(例如无限循环)。

将我的函数替换为一个名为“test_”的简单函数时,我有以下代码:

import sys
print(sys.getrecursionlimit())

def test_(x,t):
    x = x+1
    if x<t:
        test_(x=x,t=t)

print(test_(0,2971)) # output: None
print(test_(0,2972)) # RecursionError: maximum recursion depth exceeded in comparison

3000

----------------------------------- ---------------------------- RecursionError Traceback(最近一次调用 最后)在() 8 9 打印(测试_(0,2971)) ---> 10 次打印(test_(0,2972))

在 test_(x, t) 5 x = x+1 6 如果 x 7 测试_(x=x,t=t) 8 9 打印(test_(0,2971))

...最后一帧重复,从下面的帧开始...

在 test_(x, t) 5 x = x+1 6 如果 x 7 测试_(x=x,t=t) 8 9 打印(test_(0,2971))

RecursionError:比较中超出了最大递归深度

为了克服这个问题,我在不失去“运行连续性”的情况下调整了函数,以便我可以使用批处理:

for i in np.arange(0,9000,2000):
    test_(i,i+2000)

有人有更好的解决方案吗?另外,一般来说,当我们知道我们有很多迭代要做时,做递归函数是个坏主意?还有谁知道我如何在每个循环中打印递归深度?

我正在使用带有 anaconda 的 python 3.6 使用 jupyter notebook 开发 Linux 虚拟环境。

【问题讨论】:

  • 你能不能从你的函数返回当前状态,让调用者再次调用它?这样你就不会耗尽堆栈。
  • @miki,我用批处理方法测试了你的代码,它对我有用。也许你运行 for 循环的递归限制不同?
  • 感谢乔纳森的回答。我会试试这个,但我们确定错误来自以“嵌入”方式多次调用函数吗?因为,如果是这种情况,那么“批量更正”应该已经更正了错误,不是吗?
  • 谢谢@Elad!是的,它也对我有用,但就我的真实函数(而不是这个测试函数)而言,我不断收到错误......所以这就是为什么我想在每次迭代时打印递归深度以更好地理解它。

标签: python recursion stack-overflow


【解决方案1】:

我的问题是在连接不良时向某些 API 发送请求。这是一个使用bot.polling() 方法的库,所以可能是请求溢出或其他原因。

【讨论】:

    【解决方案2】:

    请检查这个问题(它对我有用): How do I get the current depth of the Python interpreter stack?

    您的代码基于该答案:

    import sys
    import inspect
    print(sys.getrecursionlimit())
    
    def test_(x,t):
        print len(inspect.stack())
        x = x+1
        if x<t:
            test_(x=x,t=t)
    
    print(test_(0,7))
    

    输出:

    22
    23
    24
    25
    26
    27
    28
    None
    

    【讨论】:

    • 非常感谢@Elad 的帮助。多亏了这一点,我提前解决了我的问题!现在我将使用它来了解主要问题,如果解决了主要问题,请随时通知您。另外,好奇的一件小事,我不明白为什么他们的错误是在这个数字不能达到3000之前......你有什么想法吗?
    • 同一个inspect模块也可以帮助你理解这一点,只需“打印inspect.stack()”你就会看到python在开始执行你的代码之前执行了一些函数。
    • 这似乎解释了为什么它从 21 开始,但对我来说它并没有解释为什么它不能达到 3000 ......也许我错过了什么?您还知道为什么有时会在笔记本中打印相同的错误:“RecursionError:比较中超出最大递归深度”,有时在终端中打印“致命的 Python 错误:无法从堆栈溢出中恢复。”?那也会有很大的帮助。非常感谢您的所有回答!
    • @miki,我相信当异常发生时它确实会达到 3000,在您的测试中 x 从 0 开始而不是当前的递归长度(这在很大程度上取决于您运行脚本的位置)另一个问题是当您捕获异常时,它已经回溯了几个堆栈,因此您不会看到 3000 只是一个接近它的数字。关于你描述的第二个问题,我无能为力。
    • 如果你在函数 'test_' 中添加以下行:' else: print(len(inspect.stack()))',然后运行 ​​'test_(0,2962)' 它将完成并打印 2983,而如果你运行 test_(0,2963),它会给出 RecursionError。因此,它不是以 3000 或 2963 结束,而是以 2983 结束(也就是说,我猜这与我从 0 开始的事实无关)。但这可能是由于您的第二个解释:)。谢谢大家!
    猜你喜欢
    • 2017-04-19
    • 2017-04-22
    • 1970-01-01
    • 2021-12-06
    • 1970-01-01
    • 1970-01-01
    • 2012-09-18
    • 1970-01-01
    • 2011-10-22
    相关资源
    最近更新 更多