核心知识点
- 上下文管理器:实现__enter__和__exit__方法的对象,用于自动管理资源(打开→使用→关闭)
- 语法:with 上下文管理器 as 变量: (代码块执行完自动调用__exit__关闭资源)
- 企业常用场景:文件操作、数据库连接、网络请求(避免资源泄露)
- 简化实现:用@contextmanager装饰器快速创建上下文管理器(无需手动实现两个魔法方法)
实战案例:MySQL连接上下文管理器(AI接口数据持久化场景)
案例需求
开发一个MySQL连接的上下文管理器,实现:自动连接数据库→执行SQL→自动关闭连接(即使执行过程中报错也能正常关闭),适配济南企业常用的MySQL 8.0版本,用于AI接口的日志数据持久化(如保存用户调用记录)。
实现步骤
1. 安装依赖:pymysql(Python连接MySQL的库)
2. 准备MySQL环境:创建数据库(ai_dev)和表(api_call_log)
3. 用@contextmanager装饰器编写上下文管理器,封装连接逻辑
4. 测试:用with语句调用上下文管理器,执行插入日志的SQL,验证连接是否自动关闭
完整代码
import pymysql
from contextlib import contextmanager
from datetime import datetime
# ------------------- 1. 先执行SQL创建数据库和表(手动在MySQL客户端执行) -------------------
# CREATE DATABASE IF NOT EXISTS ai_dev DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
# USE ai_dev;
# CREATE TABLE IF NOT EXISTS api_call_log (
# id INT AUTO_INCREMENT PRIMARY KEY,
# func_name VARCHAR(50) NOT NULL COMMENT '接口函数名',
# call_time DATETIME NOT NULL COMMENT '调用时间',
# user_id VARCHAR(32) NOT NULL COMMENT '调用用户ID',
# status TINYINT NOT NULL COMMENT '状态:1-成功,0-失败',
# created_at DATETIME DEFAULT CURRENT_TIMESTAMP
# ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='AI接口调用日志表';
@contextmanager
def mysql_connection(host: str, port: int, user: str, password: str, db: str):
"""创建MySQL数据库连接上下文管理器"""
try:
conn = pymysql.connect(
host=host,
port=port,
user=user,
password=password,
database=db,
charset="utf8mb4",
)
print("数据库连接成功")
yield conn
except pymysql.MySQLError as e:
print(f"数据库连接失败: {e}")
raise
finally:
if conn is not None: # 安全关闭
conn.close()
print("数据库连接已关闭")
# ------------------- 2. 插入ai接口调用日志 -------------------
def insert_api_call_log(
conn: pymysql.Connection,
func_name: str,
user_id: str,
status: int,
call_time: datetime = None,
):
if call_time is None:
call_time = datetime.now()
"""插入AI接口调用日志"""
sql = "INSERT INTO api_call_log (func_name, call_time, user_id, status) VALUES (%s, %s, %s, %s)"
with conn.cursor() as cursor:
cursor.execute(sql, (func_name, call_time, user_id, status))
conn.commit()
print("AI接口调用日志插入成功")
if __name__ == "__main__":
# 测试数据库连接和插入日志
mysql_config = {
"host": "localhost",
"port": 3306,
"user": "root",
"password": "root",
"db": "ai_dev",
}
with mysql_connection(**mysql_config) as conn:
# 插入一条成功的调用日志(模拟文本摘要接口调用)
insert_api_call_log(conn, "text_summary", "user_1001", 1)
# 插入一条失败的调用日志(模拟参数错误)
insert_api_call_log(conn, "text_summary", "user_1002", 0)
print("日志插入完成,请查看数据库验证")
总结
该上下文管理器等价于PHP中用try-catch-finally封装PDO连接(try中连接→执行SQL,finally中关闭连接),但Python的with语句更简洁,无需手动编写finally块,通过上下文管理器自动完成资源的“打开-关闭”生命周期管理。