You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何设置的Python递归限制未生效?递归深度超限问题排查

递归限制判断错误的原因及修正

你的代码触发RecursionError的核心问题是对sys.setrecursionlimit()的理解偏差,以及判断逻辑的疏漏:

1. 递归限制的实际含义

sys.setrecursionlimit(n)设置的是整个Python调用栈的最大层数,而非你计算的总调用次数。Python启动后,主程序(包括模块导入、顶层代码执行)已经占用了若干栈帧,所以实际可用于递归的栈层数会比n小。

比如你设置了100,但初始栈深度可能已经是3-4层,实际可用的递归深度只有96-97层左右。

2. 你的判断逻辑问题

你计算的-(len(ls) // -max_items)是处理列表所需的总调用次数(含初始调用),但递归深度是指从初始调用开始,每递归一次栈层数加1。比如处理970个元素需要97次调用,对应的递归深度是97层,加上初始栈的3层,总栈层数就会达到100,刚好触发递归限制。

修正后的代码

要准确判断是否会触发递归错误,需要结合当前的栈深度来计算剩余可用空间:

import sys

sys.setrecursionlimit(100)

max_items = 10

def foo(ls):
    # 计算处理列表所需的总调用次数(含当前调用)
    total_calls = -(len(ls) // -max_items)
    # 获取当前栈深度
    current_depth = sys.getrecursiondepth()
    # 剩余可用于递归的栈层数
    available_depth = sys.getrecursionlimit() - current_depth
    # 所需的递归次数是总调用次数减1(当前调用已占用一层)
    if (total_calls - 1) > available_depth:
        raise ValueError("List is too long. You'll hit the recursion limit")
    
    ls, ls_ = ls[:max_items], ls[max_items:]
    print(len(ls_))
    if len(ls_) > 0:
        foo(ls_)

foo(list(range(970)))

补充说明

  • sys.getrecursiondepth()(Python 3.10+可用)能准确获取当前调用栈的层数,避免了对初始栈深度的猜测。
  • 如果使用低于3.10的Python版本,可以通过sys._getframe().f_depth来获取当前栈深度(注意sys._getframe()是私有API,谨慎使用)。

内容的提问来源于stack exchange,提问作者Alexander Soare

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.10 04:07:49