sys.setrecursionlimit对@cache装饰函数无效?求因及解决
递归缓存装饰器的递归限制问题解析
问题原因
functools.cache(包括lru_cache)是用C扩展实现的,它的递归调用走的是系统C栈,而非Python解释器维护的Python栈。你通过sys.setrecursionlimit()设置的只是Python栈的递归深度上限,对C栈完全无效。
系统默认的C栈大小通常远小于100000(比如多数系统对应递归深度仅几千),所以当用@cache装饰的递归函数调用到600层时,就触发了C栈溢出,报错信息自然和Python栈超限的不一样。
而自定义缓存装饰器、可调用类都是纯Python代码实现,递归调用全程走Python栈,所以会严格遵守sys.setrecursionlimit()设置的上限,能跑到90000层也不奇怪。
解决方法
- 改用纯Python缓存装饰器:放弃
functools.cache,用自己实现的纯Python缓存逻辑,或者第三方库中纯Python版本的缓存装饰器,这样递归调用会走Python栈,遵循你设置的递归限制。 - 将递归改为迭代实现:这是最稳妥的方案。把递归逻辑改成循环迭代的形式,彻底绕开栈深度限制,不管是C栈还是Python栈都不会有溢出问题。
- 调整系统C栈大小(不推荐):如果一定要用
functools.cache,可以尝试调整系统的C栈上限。比如Linux下用ulimit -s命令增大栈大小,Windows下可能需要修改编译参数或借助工具,但这种方法跨平台性差,还可能引发其他系统级问题,不建议在生产环境使用。
内容的提问来源于stack exchange,提问作者Zachary Barbanell
相关产品推荐
相关产品推荐

