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

关于Python上下文管理器__enter__、__exit__与mysql.connector使用疑问

原代码错误点说明
  • 你把连接逻辑写到了单独的co()方法里,co()没有返回值,所以with后面调用co()拿到的是None,无法赋值给log
  • __enter__方法是空的,没有返回任何内容,就算不调用co(),as后面的变量也是None
  • __exit__方法没有写关闭连接的逻辑,会导致连接泄漏
  • self.raws = self.crouser.execute(self.que)这里赋值是无效的,execute不会返回查询结果,fetchall()的返回值才是你要的目标数据
问题解答

1. 查询结果的返回位置

查询执行和结果获取的逻辑应该放到__enter__方法中,__enter__的返回值会直接赋值给with语句as后面的变量,也就是你要的查询结果。

2. 数据库连接的关闭时机

__exit__方法是with代码块执行结束后(哪怕中间代码报错)一定会触发的逻辑,你要在这个方法里依次关闭游标、关闭数据库连接,就能保证连接不会泄露。

3. with语法的正确使用方式

with后面直接跟你定义的类实例即可,不需要额外调用自定义方法,实例进入with上下文时会自动触发__enter__的逻辑,退出时自动触发__exit__的逻辑。

修正后的完整代码
import mysql.connector

class Tak:
    def __init__(self, host1, user1, password1, db1, aat, que1):
        self.host = host1
        self.user = user1
        self.password = password1
        self.database = db1
        self.auth_plugin = aat
        self.que = que1
        # 提前初始化连接和游标变量,避免报错时属性不存在
        self.conn = None
        self.cursor = None

    def __enter__(self):
        try:
            # 初始化数据库连接
            self.conn = mysql.connector.connect(
                host=self.host,
                user=self.user,
                password=self.password,
                database=self.database,
                auth_plugin=self.auth_plugin,
                charset='utf8'
            )
            self.cursor = self.conn.cursor()
            # 执行查询
            self.cursor.execute(self.que)
            # 返回查询结果,直接赋值给as后的变量
            return self.cursor.fetchall()
        except mysql.connector.Error as err:
            print(f"数据库操作出错:{err}")
            # 出错返回空避免赋值报错
            return []

    def __exit__(self, exc_type, exc_val, exc_tb):
        # 不管with块内是否报错,都关闭资源
        if self.cursor:
            self.cursor.close()
        if self.conn:
            self.conn.close()
        # 返回False代表不吞掉with块内的异常,有错误会正常抛出
        return False


# 正确的with调用方式
with Tak(
    host1="localhost",
    user1="root",
    password1="1234",
    db1="local_db",
    aat='mysql_native_password',
    que1='select * from nand'
) as log:
    print(log)
额外注意事项
  • 类名建议遵循Python大驼峰命名规范,不要用全小写的命名,可读性更高
  • mysql.connector.errors是异常模块,捕获异常的时候要写mysql.connector.Error才是正确的异常类
  • 如果后续要做增删改操作,需要在__exit__里判断有没有异常,没有异常就调用self.conn.commit()提交事务,纯查询场景不需要提交

内容的提问来源于stack exchange,提问作者Mark

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.04 19:06:00