python 递归深度限制是为防止c栈溢出导致进程被系统杀死,而非崩溃;sys.setrecursionlimit()仅修改计数器,不扩展实际栈空间,真正安全的做法是将递归重写为迭代。

RecursionError: maximum recursion depth exceeded 不是崩溃,而是 Python 主动拦停——它在 C 栈真正溢出前就抛错,防止进程被操作系统直接杀死。
为什么必须设限?因为 CPython 共享系统线程栈
Python 函数调用复用操作系统的 C 调用栈(不是 Python 堆内存),默认每线程约 1–8MB。每层递归至少占 1–2KB 栈帧,1000 层 ≈ 1–2MB,留了余量防爆栈。
不设限的话,递归会一路写到栈底,触发 Segmentation fault(Linux/macOS)或 Windows fatal exception: stack overflow(Windows),连 traceback 都没机会打印。
sys.setrecursionlimit() 只改计数器,不扩栈空间
这个函数只是调整解释器内部的“层数计数器”,底层 C 栈大小完全不受影响:
• 在多线程里调用 sys.setrecursionlimit() 是全局生效,但子线程栈更小,实际撑不住设定值
• 设成 sys.setrecursionlimit(100000) 后,大概率还没走到第 10000 层就静默退出(Killed: 9)
• __str__、__repr__、日志装饰器等隐式递归场景,会让真实深度远超预期
哪些递归真需要调限?其实极少
只有同时满足以下条件时,才考虑小幅上调:
• 递归逻辑干净、无隐式调用(比如没在 print(obj) 里触发 obj.__str__ 再调自己)
• 深度可预估(如解析用户提交的 YAML,已知最多 300 层)
• 已确认系统栈余量:Unix 下用 resource.getrlimit(resource.RLIMIT_STACK),跨平台用 threading.stack_size()
• 必须在 if __name__ == '__main__': 开头尽早设置,并包 try/except RecursionError 回滚
绝大多数情况该重写为迭代
树遍历、DFS、回溯、AST 解析——这些不是“能不能转”,而是“必须转”:
• 用 list 或 collections.deque 模拟栈,内存开销明确可控
• 非尾递归(如中序遍历)需额外存状态(当前节点 + 已处理分支),但比赌栈空间安全得多
• 尾递归(如阶乘累加)直接拆成 while 循环,零栈增长
• 迭代版本可打断、可调试、可监控,生产环境不依赖解释器的栈管理策略
sys.setrecursionlimit() 能解决深度问题——它只是把“报错”延迟到更不可控的阶段。Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











