Python上下文管理器类:捕获__init__/__enter__异常并维持程序执行
解决数据库上下文管理器连接异常不中断后续操作的问题
要实现单个数据库连接失败不影响后续数据库操作的需求,我们需要修改DB类的实现,在连接阶段捕获异常,并返回一个安全的"空游标"对象,同时确保资源关闭逻辑不会因连接失败而报错。以下是具体实现:
修改后的DB类代码
class DummyCursor: """空游标类,连接失败时返回,避免with块内代码报错""" def insert_to_db_word(self, word): # 可选:记录连接失败的操作日志 print(f"数据库连接失败,跳过插入: {word}") class DB: def __init__(self, host, user, password, db_name): self.host = host self.user = user self.password = password self.db_name = db_name self.connection = None self.cursor = None self.connect_success = False # 标记是否连接成功 def __enter__(self): try: # 尝试连接数据库 self.connection = name_some_module_for_sql.connection( self.host, self.user, self.password, self.db_name ) self.cursor = self.connection.cursor() self.connect_success = True return self.cursor except Exception as e: # 捕获连接异常,打印错误(或写入日志) print(f"连接数据库失败: {str(e)}") # 返回空游标,确保with块内的方法调用不会报错 return DummyCursor() def __exit__(self, exc_type, exc_val, exc_tb): # 仅当连接成功时,才关闭资源 if self.connect_success: if self.cursor: try: self.cursor.close() except Exception as e: print(f"关闭游标失败: {str(e)}") if self.connection: try: self.connection.close() except Exception as e: print(f"关闭连接失败: {str(e)}") # 返回True表示已处理异常,不向上抛出 return True
关键修改点说明
空对象模式(DummyCursor):
当数据库连接失败时,返回一个预先定义的DummyCursor对象,它的insert_to_db_word方法会跳过实际操作(或记录日志),这样with块内的代码不会因为游标不存在而抛出AttributeError。连接阶段异常捕获:
在__enter__方法中捕获连接数据库时的所有异常,标记连接状态,并返回安全的空游标,保证程序不会因单个数据库连接失败而中断。安全的资源关闭逻辑:
在__exit__中先检查connect_success标记,仅当连接成功时才尝试关闭游标和连接,避免因connection或cursor未初始化而引发新的异常。连接状态标记:
新增connect_success属性,方便外部代码判断当前数据库是否连接成功(如果需要的话)。
使用方式(和原代码完全兼容)
with DB(1, 1, 1, 1) as cursor: # 即使db_1连接失败,后续代码仍会执行 cursor.insert_to_db_word("Hello") cursor.insert_to_db_word("My") cursor.insert_to_db_word("Dear") cursor.insert_to_db_word("Friend") with DB(2, 2, 2, 2) as cursor: # db_2正常执行 cursor.insert_to_db_word("Hello") cursor.insert_to_db_word("My") cursor.insert_to_db_word("Dear") cursor.insert_to_db_word("Friend") with DB(3, 3, 3, 3) as cursor: # db_3正常执行 cursor.insert_to_db_word("Hello") cursor.insert_to_db_word("My") cursor.insert_to_db_word("Dear") cursor.insert_to_db_word("Friend")
这样修改后,即使第一个数据库连接失败,后续两个数据库的插入操作依然会正常执行,程序不会中断。
内容的提问来源于stack exchange,提问作者temp1
相关产品推荐
相关产品推荐

