You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

关键修改点说明

  1. 空对象模式(DummyCursor):
    当数据库连接失败时,返回一个预先定义的DummyCursor对象,它的insert_to_db_word方法会跳过实际操作(或记录日志),这样with块内的代码不会因为游标不存在而抛出AttributeError。

  2. 连接阶段异常捕获:
    在__enter__方法中捕获连接数据库时的所有异常,标记连接状态,并返回安全的空游标,保证程序不会因单个数据库连接失败而中断。

  3. 安全的资源关闭逻辑:
    在__exit__中先检查connect_success标记,仅当连接成功时才尝试关闭游标和连接,避免因connection或cursor未初始化而引发新的异常。

  4. 连接状态标记:
    新增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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.27 04:07:01