深入解析:【JavaSE】十九、JVM运行流程 类加载Class Loading
2026/1/18 14:21:17
先明确核心价值:上下文管理器是为了解决「资源打开后必须关闭」的问题(比如文件打开后忘关、数据库连接泄露),通过with语句自动执行「进入时初始化」和「退出时清理」逻辑,替代繁琐的try/finally,让代码更简洁、健壮。
核心语法(使用层面):
python
运行
with 上下文管理器对象 as 变量: # 执行核心逻辑(资源使用) # 离开with块后,自动执行清理操作(如关闭文件/连接)通过定义类并实现两个魔法方法:
__enter__(self):进入with块时执行,返回值会被as后的变量接收;__exit__(self, exc_type, exc_val, exc_tb):离开with块时执行(无论是否报错),负责清理资源。python
运行
class FileContextManager: """自定义文件上下文管理器""" def __init__(self, file_path, mode="r"): # 初始化:接收资源参数(文件路径、打开模式) self.file_path = file_path self.mode = mode self.file = None # 初始化文件句柄 def __enter__(self): """进入with块时执行:打开文件""" print("执行__enter__:打开文件") self.file = open(self.file_path, self.mode, encoding="utf-8") return self.file # 返回值给as后的变量 def __exit__(self, exc_type, exc_val, exc_tb): """离开with块时执行:关闭文件(核心清理逻辑)""" print("执行__exit__:关闭文件") if self.file: # 避免文件未打开时调用close() self.file.close() # 可选:处理with块内的异常(返回True则异常被吞,False则抛出) if exc_type: print(f"捕获异常:{exc_type}, {exc_val}") # return True # 注释打开则异常不会向外抛出 return False # 测试使用 if __name__ == "__main__": # 正常使用(自动打开→写入→关闭) with FileContextManager("test.txt", "w") as f: f.write("Python上下文管理器测试") # 测试异常场景(仍会关闭文件) try: with FileContextManager("test.txt", "r") as f: # 故意触发异常 1 / 0 f.read() except ZeroDivisionError: print("外部捕获到异常")__exit__的三个异常参数:exc_type:异常类型(如ZeroDivisionError),无异常则为None;exc_val:异常实例(具体错误信息);exc_tb:异常追踪栈;__exit__返回值:返回True会吞掉异常(外部捕获不到),返回False(默认)则异常向外抛出,建议保留默认(便于排查问题);contextlib.contextmanager装饰器(简洁版)这是 Python 内置的简化方案,通过生成器函数替代类的两个魔法方法,代码量更少,适合简单场景。
yield之前的代码 =__enter__逻辑;yield之后的代码 =__exit__逻辑;yield的返回值 =as后的变量。python
运行
from contextlib import contextmanager @contextmanager # 装饰器将生成器转为上下文管理器 def file_context_manager(file_path, mode="r"): """用生成器实现文件上下文管理器""" # 第一步:执行__enter__逻辑(打开文件) file = None try: print("执行enter逻辑:打开文件") file = open(file_path, mode, encoding="utf-8") yield file # 返回值给as,暂停执行,进入with块 except Exception as e: print(f"with块内异常:{e}") finally: # 第二步:执行__exit__逻辑(关闭文件,无论是否报错) print("执行exit逻辑:关闭文件") if file: file.close() # 测试使用(和类实现效果完全一致) with file_context_manager("test.txt", "w") as f: f.write("装饰器版上下文管理器") with file_context_manager("test.txt", "r") as f: print(f.read())try/finally包裹逻辑:确保yield后的清理代码(如关闭文件)无论是否报错都会执行;yield,多了会报错。用上下文管理器管理 MySQL 连接(更贴近实际开发):
python
运行
import pymysql from contextlib import contextmanager # 用装饰器实现数据库连接上下文管理器 @contextmanager def mysql_conn(host, user, password, db): conn = None cursor = None try: # 初始化连接(enter逻辑) conn = pymysql.connect(host=host, user=user, password=password, db=db) cursor = conn.cursor() yield cursor # 返回游标给with块 except Exception as e: conn.rollback() # 出错回滚 raise e # 抛出异常供外部处理 finally: # 清理资源(exit逻辑) if cursor: cursor.close() if conn: conn.close() # 使用:自动连接→执行SQL→关闭连接 with mysql_conn("localhost", "root", "123456", "test_db") as cur: cur.execute("SELECT * FROM user;") print(cur.fetchall())| 实现方式 | 优点 | 缺点 | 适用场景 |
|---|---|---|---|
| 类实现 | 灵活,支持复杂逻辑(异常处理、参数校验) | 代码量稍多 | 生产环境、复杂资源管理 |
| 装饰器 + 生成器 | 代码简洁,新手友好 | 仅支持简单逻辑 | 小工具、快速实现 |
__enter__(初始化)和__exit__(清理),with语句会自动触发这两个步骤;__exit__/yield 后代码都会执行,确保资源 100% 被清理;