使用with调用数据库连接触发TypeError:NoneType不支持上下文管理器协议
错误根源
这个错误的核心是self.DB_connection()返回了None,或者返回的对象没有实现上下文管理器的__enter__/__exit__方法。pymysql的Connection本身支持上下文管理器,所以问题大概率出在你的DB_connection方法没有正确返回有效连接——比如配置读取失败、连接建立时出错导致返回了None。
解决方案
1. 修正DB_connection方法,确保返回有效连接
首先要保证配置读取正常,并且连接失败时抛出异常而非返回None,避免with语句拿到无效对象:
import pymysql import json class DBHandler: def __init__(self, config_path): # 读取JSON配置文件,提前处理配置读取异常 try: with open(config_path, 'r', encoding='utf-8') as f: self.db_config = json.load(f) except (FileNotFoundError, json.JSONDecodeError) as e: raise RuntimeError(f"配置文件读取失败: {e}") def DB_connection(self): try: # 建立并返回数据库连接,pymysql.Connection本身支持上下文管理器 return pymysql.connect( host=self.db_config['host'], user=self.db_config['user'], password=self.db_config['password'], database=self.db_config['database'], charset='utf8mb4' ) except pymysql.MySQLError as e: # 连接失败直接抛出异常,不返回None raise RuntimeError(f"数据库连接失败: {e}")
2. 正确编写嵌套with语句
嵌套with可以同时管理数据库连接和游标,两者都会在with块结束后自动释放资源,无需手动调用close():
def logging_sp(self, sp_name, params): # 外层with管理连接,内层with管理游标 with self.DB_connection() as cnxn: with cnxn.cursor() as cursor: try: # 执行存储过程 cursor.callproc(sp_name, params) # 读取存储过程返回的结果(按需调整) result = cursor.fetchall() # 提交事务(如果存储过程涉及写操作) cnxn.commit() return result except pymysql.MySQLError as e: # 出错回滚事务 cnxn.rollback() raise RuntimeError(f"存储过程执行失败: {e}")
额外排查点
- 检查JSON配置文件的键名是否和代码中的
host/user/password/database完全匹配,避免键名拼写错误导致配置读取不全。 - 确认数据库服务正常运行、网络连通性正常,以及配置中的账号权限足够执行目标存储过程。
内容的提问来源于stack exchange,提问作者Forgottenluv
相关产品推荐
相关产品推荐

