RecursionError是CPython为防止C栈溢出而设的主动防护机制,非代码逻辑错误;默认递归深度约1000层,超限即拦截,避免Segmentation fault。

RecursionError不是代码写错了,是Python主动踩刹车
Python 报 RecursionError: maximum recursion depth exceeded,根本原因不是逻辑错误,而是 CPython 解释器在调用栈快撑爆时「提前拦截」——它默认只允许约 1000 层函数调用嵌套(可通过 sys.getrecursionlimit() 查看),目的是防止 C 层栈溢出导致整个解释器崩溃(比如 Segmentation fault)。
每次递归调用都会在系统栈上压入一个栈帧,存参数、局部变量、返回地址等。栈内存有限(Linux 默认线程栈约 8MB,Windows 更小),层数一多就直接触顶。所以这不是“你的数据太大”,而是“调用链太深”。
哪些操作最容易触发这个错误
常见场景不是冷门边缘 case,而是日常高频误用:
-
json.loads()或pprint.pprint()处理深度超过 500 层的嵌套字典/列表(尤其含循环引用时) - 手写递归遍历树结构,比如二叉树 DFS 或文件目录递归扫描,节点深度 > 1000
- 快速排序最坏情况(已排序数组+取首元素为 pivot),递归深度退化为
O(n) - 异步函数里写同步递归重试:
async def fetch(...): ... return await fetch(...),协程帧持续堆积 - 类中误写
__getattr__,访问不存在属性时又触发自身,形成隐式死循环
为什么不能无脑调高 sys.setrecursionlimit()
设成 sys.setrecursionlimit(10000) 看似解决问题,实则埋雷:
- 它不增加实际可用栈空间,只是放宽 Python 层检查;底层 C 栈仍可能溢出,引发不可捕获的
Segmentation fault - macOS/Linux 下易崩,Windows 上可能静默失败或内存耗尽
- 多线程环境每个线程需单独设置,且
threading.stack_size()才真正控制栈容量 - 生产环境设成
100000等同于放弃防御,等于把问号当句号
真正该盯住的三个关键点
遇到 RecursionError,先别动 sys.setrecursionlimit(),立刻检查:
- 递归终止条件是否覆盖所有路径?比如
if n 漏了负数输入,if node没防住循环引用 - 每次递归参数是否严格收敛?传
n-1是 OK 的,传n-0.5或未变的n就会卡死 - 是不是本该用迭代?95% 的树遍历、嵌套扁平化、JSON 处理,用
list做显式栈(如stack = [(root, 0)])更稳、更快、可调试
深层嵌套不是数据问题,是控制流设计问题。栈帧不会说谎,它报错时,往往意味着你正在用语言最不擅长的方式解决一个问题。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











