Python 上下文管理器(Context Manager)
上下文管理器是 Python 中管理资源的神器,核心作用是自动分配/释放资源,不用手动写繁琐的关闭、清理代码,避免资源泄漏。
最常见的场景:文件操作、数据库连接、网络请求、线程锁等。
一、核心概念
1. 它解决什么问题?
以前我们操作文件/连接,必须手动 close(),一旦忘记或出错,资源就会泄漏:
# 不推荐:容易忘记关闭,出错时还会跳过 close()
f = open("test.txt", "w")
f.write("hello")
# 若这里报错,文件永远不会关闭
f.close()
上下文管理器会自动执行清理操作,无论代码正常运行还是报错。
2. 核心语法:with 语句
这是上下文管理器最常用、最简单的用法:
with 上下文管理器 as 变量:
代码块
执行流程:
- 进入
with时 → 执行初始化/资源申请 - 执行代码块
- 退出
with时 → 自动执行资源释放/关闭(哪怕代码报错)
二、最常用的内置上下文管理器
1. 文件操作(最经典)
# 自动打开、自动关闭文件,无需写 close()
with open("test.txt", "r", encoding="utf-8") as f:
content = f.read()
print(content)
2. 线程锁
import threading
lock = threading.Lock()
with lock: # 自动加锁、自动解锁
# 安全操作共享数据
pass
3. 临时文件、数据库连接等
Python 很多内置/第三方库都支持 with 语法。
三、自定义上下文管理器(两种方式)
方式1:类实现(最标准)
实现两个魔法方法:
__enter__():进入with时执行(申请资源)__exit__():退出with时执行(释放资源)
class MyResource:
# 初始化
def __init__(self, name):
self.name = name
# 进入 with 时调用
def __enter__(self):
print(f"【开启】资源:{self.name}")
return self # 返回的值会被 as 接收
# 退出 with 时调用(自动处理异常)
def __exit__(self, exc_type, exc_val, exc_tb):
print(f"【关闭】资源:{self.name}")
# exc_type:异常类型(无异常则为 None)
return True # 可选:True 表示忽略异常
# 使用
with MyResource("测试资源") as res:
print(f"使用资源:{res.name}")
输出:
【开启】资源:测试资源
使用资源:测试资源
【关闭】资源:测试资源
方式2:装饰器实现(更简洁)
用 contextlib.contextmanager 装饰生成器函数,一行代码快速实现:
yield之前 =__enter__yield之后 =__exit__
from contextlib import contextmanager
@contextmanager
def my_resource(name):
# 进入 with:资源申请
print(f"【开启】{name}")
try:
yield name # 返回给 as 变量
finally:
# 退出 with:资源释放(无论是否报错都会执行)
print(f"【关闭】{name}")
# 使用
with my_resource("简洁版资源") as res:
print(f"使用:{res}")
效果和类版本完全一样,代码更短!
四、上下文管理器的优势
- 代码更简洁:不用写
try...finally手动关闭 - 安全可靠:无论代码正常/报错/中断,都会执行清理
- 可读性高:一眼看出资源的作用范围
- 通用强大:文件、数据库、网络、锁、临时目录都能用
五、实用小技巧:同时管理多个资源
# 同时打开两个文件,自动全部关闭
with open("a.txt") as f1, open("b.txt") as f2:
data1 = f1.read()
data2 = f2.read()
总结
- 上下文管理器 =
with语句,专门自动管理资源 - 核心:进入时申请,退出时释放
- 用法:
- 直接用内置(
open()、锁) - 自定义:类(
__enter__/__exit__)或装饰器(@contextmanager)
- 直接用内置(
- 好处:安全、简洁、无资源泄漏