如何排查代码中突发的RecursionError递归深度超出问题
首先,这个RecursionError的根源几乎可以肯定是循环实例化——你的当前类(就是定义了那行self.background = Background(...)的类)在初始化时创建Background对象,而Background类的初始化过程中,又反过来触发了当前类的实例化,形成了无限循环调用,直到达到Python的递归深度上限。
下面是一步步定位问题的具体方法:
直接检查Background类的初始化逻辑
打开定义Background的文件,逐行梳理它的__init__方法:- 有没有直接写类似
self.parent = YourCurrentClass(...)的代码?(这里的YourCurrentClass就是你在q.py里的那个类) - 有没有调用某个函数,而那个函数内部偷偷创建了
YourCurrentClass的实例? - 有没有导入某个模块,而该模块在加载阶段就会自动实例化
YourCurrentClass?
- 有没有直接写类似
排查模块间的导入循环
比如你的q.py导入了Background所在的模块,而Background所在的模块又反过来导入了q.py里的YourCurrentClass。这种互相导入的情况,有时候会触发意外的类实例化,间接形成递归循环。添加调试打印追踪调用链
临时在两个类的__init__开头加调试代码,直观看到调用顺序:
先导入sys模块,然后在你的类的__init__开头加:print(f"正在创建当前类实例,当前递归深度: {sys.getrecursiondepth()}")再在
Background的__init__开头加:print(f"正在创建Background实例,当前递归深度: {sys.getrecursiondepth()}")运行代码后,你会看到这两行打印交替出现,直到报错,这就坐实了循环调用的问题。
检查装饰器或元类的影响
有时候类上的装饰器,或者自定义元类,会在实例化时触发额外逻辑——比如自动创建关联类的实例,不小心搞出了循环。检查你的类和Background类有没有被装饰器修饰,或者使用了自定义元类。对比历史代码找改动点
既然之前代码运行正常,那问题肯定出在最近的修改里。用版本控制工具(比如Git)对比最近的代码改动,重点看Background类的初始化逻辑,或者q.py里第523行附近的代码有没有新增或修改的内容。
举个典型的错误例子,你就能明白循环的由来:
# q.py from background import Background class Game: def __init__(self): self.background = Background() # 你的第523行 # background.py from q import Game class Background: def __init__(self): self.game = Game() # 这里又创建了Game实例,形成无限递归
解决的核心思路就是打破循环:比如把需要的实例通过参数传入(依赖注入),或者延迟初始化(等真正需要的时候再创建,而不是在__init__里直接创建)。
内容的提问来源于stack exchange,提问作者Dan Lambert

