自定义MySQL适配器类析构时报弱引用对象不存在错误如何解决
MySQL适配器析构方法弱引用报错排查与修复方案
报错核心原因
你遇到的ReferenceError: weakly-referenced object no longer exists报错本质是Python析构函数__del__的执行特性导致的:Python解释器退出时,对象属性的销毁顺序没有明确保证,mysql.connector的游标对象内部持有连接对象的弱引用,当__del__执行时,连接对象可能已经被GC优先回收,导致游标对应的弱引用失效。
另外你的初始化代码存在笔误:__init__接收了database参数,但没有赋值给实例属性self.database,直接在connect方法中调用self.database会触发属性未定义问题,需要先修正。
排查步骤
- 打印析构执行时的实例属性状态:在
__del__方法开头通过hasattr(self, 'cursor')、hasattr(self, 'connection')判断属性是否已经被回收,确认是否是销毁顺序导致的问题。 - 验证实例生命周期:如果适配器实例存放在Flask的请求/应用上下文中,添加日志确认实例销毁时间点和Flask shutdown流程的先后顺序,排查上下文提前清理属性的可能性。
- 排除驱动版本问题:确认你使用的
mysql-connector-python版本没有已知的弱引用相关bug,可升级到最新稳定版本复现验证。
修复方案
方案1:优先使用上下文管理器替代__del__(最推荐)
主动管理资源生命周期,避免依赖GC自动回收,给适配器类实现上下文协议,使用时通过with语句调用,保证资源按正确顺序释放:
class MySQLAdapter: def __init__(self, database): # 修正笔误,先给实例属性赋值 self.database = database self.connection = mysql.connector.connect( host = "xxx", database = self.database, port = "xxx", user = "xxx", password = "xxx", ) self.cursor = self.connection.cursor() def __enter__(self): return self def __exit__(self, exc_type, exc_val, exc_tb): # 按游标先、连接后的顺序释放,先判断属性有效性 if hasattr(self, 'cursor') and self.cursor is not None: self.cursor.close() if hasattr(self, 'connection') and self.connection.is_connected(): self.connection.close() # 使用示例 with MySQLAdapter(database="test") as db: db.cursor.execute("SELECT * FROM xxx")
方案2:Flask场景下注册全局销毁回调
如果你的适配器是Flask应用内的全局/上下文绑定实例,通过Flask的teardown_appcontext钩子主动释放资源,完全不需要依赖__del__:
from flask import Flask, g app = Flask(__name__) def get_db_adapter(): if 'db' not in g: g.db = MySQLAdapter(database="your_db") return g.db # 应用上下文销毁时自动执行 @app.teardown_appcontext def close_db_resources(error): db = g.pop('db', None) if db is not None: if hasattr(db, 'cursor'): db.cursor.close() if hasattr(db, 'connection') and db.connection.is_connected(): db.connection.close()
方案3:保留__del__做兜底清理(仅作为补充方案)
如果必须保留__del__逻辑,添加有效性判断和异常捕获,避免操作已回收的对象:
def __del__(self): try: if hasattr(self, 'cursor'): self.cursor.close() except ReferenceError: pass try: if hasattr(self, 'connection') and self.connection.is_connected(): self.connection.close() except ReferenceError: pass
内容的提问来源于stack exchange,提问作者linkedin
相关产品推荐
相关产品推荐

