Python 的 with ... as ... 上下文管理器

一、核心作用

  • 自动执行「进入操作」(如打开文件、创建连接)和「退出操作」(如关闭文件、释放连接)
  • 即使代码块中发生异常,也能保证退出操作被执行(相当于自带 try-finally 但更简洁)

二、 基本语法结构

python 复制代码
with 上下文表达式 as 变量名: 
    # 代码块(使用资源的逻辑) 
# 代码块结束后,自动执行退出操作(无需手动关闭)
  • 「上下文表达式」:返回一个上下文管理器对象 (如 open()、自定义的 对象 实例)
  • 变量名」:可选,接收上下文管理器的 __enter__() 方法返回的值(不是管理器对象本身

三、工作原理

一个对象能被with使用,必须实现两个特殊方法

  1. __enter__(self):进入 with 代码块时执行。
    • 负责初始化资源(如打开文件、连接数据库)
    • 返回的值会赋值给 as 后的变量名
  2. __exit__(self, exc_type, exc_val, exc_tb):退出 with 代码块时执行(无论正常结束还是异常结束)
    • 负责释放资源(如关闭文件、断开连接)
    • 接收异常信息,可返回 True 表示忽略异常。

示例:自定义简单上下文管理器

python 复制代码
class MyFileReader: 
    def __init__(self, file_path):
        self.file_path = file_path 
        self.file = None # 进入with代码块时执行 
    def __enter__(self): 
        self.file = open(self.file_path, 'r', encoding='utf-8') 
        return self.file # 返回文件对象,赋值给as后的变量 # 退出with代码块时执行 
    def __exit__(self, exc_type, exc_val, exc_tb): 
        if self.file: 
            self.file.close() # 自动关闭文件 
        # 若返回True,会忽略代码块中的异常;返回None/False则会抛出异常 
        return False 
# 使用 with 
MyFileReader('test.txt') as f: 
    content = f.read() # 直接使用__enter__返回的文件对象 
    # 代码块结束后,自动调用__exit__关闭文件

四、常见使用场景

1.操作文件

替代手动open()/close(),避免忘记关闭文件

python 复制代码
# 正确用法:自动关闭文件 
with open('test.txt', 'r', encoding='utf-8') as f: 
    content = f.read() 
# 等价于(但更简洁) 
f = open('test.txt', 'r', encoding='utf-8') 
try: 
    content = f.read() 
finally: 
    f.close()

2.使用自定义工具类

只有实现了 __enter____exit__,才能直接用 with

3.多资源同时管理

可在一个 with 中管理多个资源(用逗号分隔),按顺序进入、逆序退出:

python 复制代码
# 同时打开两个文件,自动关闭 
with open('a.txt', 'r') as f1, open('b.txt', 'w') as f2: 
    content = f1.read() 
    f2.write(content)

4. 数据库连接/网络连接

自动释放连接,避免连接池耗尽:

python 复制代码
import pymysql

with pymysql.connect(host='localhost', user='root', password='123456', db='test') as conn:
    with conn.cursor() as cursor:
        cursor.execute('SELECT * FROM users')
        result = cursor.fetchall()
# 自动关闭cursor和conn

五、关键注意事项

  1. as 后的变量是 __enter__ 的返回值,不是上下文管理器对象:
    • open()__enter__ 返回文件对象,所以 as ff 是文件对象,不是 open() 的返回值
    • 你的 MyFileReader__enter__ 返回 self,所以 readerMyFileReader 实例,可调用其方法。
  2. 异常处理
    • 代码块中发生异常时,__exit__ 仍会执行(保证资源释放)
    • __exit__ 返回 True,异常会被静默处理(不抛出);返回 FalseNone,异常会正常抛出
  3. 并非所有对象都能用于 with
    • 必须实现 __enter____exit__ 方法(即「上下文管理器协议」)
    • 常见支持的对象:open()threading.Lockpymysql.connect、自定义实现协议的类
  4. 适用于「需要成对操作」的场景
    • 打开 / 关闭、连接 / 断开、加锁 / 解锁等,用 with 能简化代码并避免遗漏

六、进阶:用contextlib简化自定义上下文管理器

如果不想手动实现 __enter____exit__,可使用 contextlib.contextmanager 装饰器(基于生成器):

python 复制代码
from contextlib import contextmanager

@contextmanager
def my_file_reader(file_path):
    # 相当于__enter__的逻辑
    f = open(file_path, 'r', encoding='utf-8')
    yield f  # 返回值赋值给as后的变量,暂停在这里执行代码块
    # 代码块结束后,执行以下(相当于__exit__的逻辑)
    f.close()

# 使用方式不变
with my_file_reader('test.txt') as f:
    content = f.read()
相关推荐
青 春 记 忆2 小时前
Dify Docker Compose 通用无损升级指南:从备份、双版本预演到切换与回滚
运维·人工智能·python·docker·容器
GlueNa2SiO32 小时前
03-Flask模板引擎Jinja2详解
笔记·python·flask
临沂GEO5 小时前
GEO搜索优化科普|正规地理位置流量运营入门指南
大数据·人工智能·python·流量运营
大模型码小白5 小时前
Spring AI Tool 实现自然语言操作 MySQL 数据库详解
服务器·开发语言·数据库·人工智能·python·mysql·spring
荷蒲6 小时前
【小白量化Qbuddy】利用AI学习中文Python
人工智能·python·学习
数据狐(Datafox)8 小时前
京东商品列表API技术解析与落地应用(含标准 JSON 示例)
java·大数据·前端·人工智能·python·数据分析·json
量化吞吐机8 小时前
2026年下半年手工交易规则走向量化表达,产品该先接住哪一步
人工智能·python
Metaphor6929 小时前
使用 Python 读取和删除 Excel 文件属性
python·excel
迷迭香yy9 小时前
Python构建转融券多空识别系统从接口到因子的全流程 IG50免费开源股票数据API接口
开发语言·python·开源
月光船幽幽10 小时前
真实即粗糙,光滑是伪造
人工智能·python