依窗看雨 發表於 2026-4-8 22:59:00

📦 Python上下文管理器:with语句与__enter__/__exit__完全指南

<h2>📦 引言</h2>
<p>在Python编程中,<strong>上下文管理器(Context Manager)</strong>是一个强大而优雅的特性。它通过<code>with</code>语句实现了资源的自动获取和释放,让代码更加简洁、可读性更强,同时有效避免了资源泄漏问题。本文将深入探讨上下文管理器的工作原理、实现方式以及实际应用场景。</p>
<h2>🔍 为什么需要上下文管理器?</h2>
<p>在没有上下文管理器之前,我们处理文件操作通常是这种方式:</p>
<pre><code># 传统方式 - 容易出错
f = open('data.txt', 'r')
data = f.read()
f.close()# 如果上面出错,这里不会执行!</code></pre>
<p>使用<code>try-finally</code>改进:</p>
<pre><code># try-finally 方式 - 代码冗长
f = open('data.txt', 'r')
try:
    data = f.read()
finally:
    f.close()# 确保关闭,但代码繁琐</code></pre>
<p>而使用<code>with</code>语句:</p>
<pre><code># with 语句 - 简洁优雅
with open('data.txt', 'r') as f:
    data = f.read()
# 自动关闭,无需手动处理!</code></pre>
<h2>⚙️ 上下文管理器的工作原理</h2>
<p>上下文管理器的核心是两个特殊方法:</p>
<ul>
<li><code>__enter__()</code>: 进入上下文时调用,返回的资源会赋值给<code>as</code>后的变量</li>
<li><code>__exit__(exc_type, exc_val, exc_tb)</code>: 退出上下文时调用,处理异常清理工作</li>
</ul>
<h2>🛠️ 自定义上下文管理器</h2>
<h3>方式一:基于类的实现</h3>
<pre><code>class DatabaseConnection:
    def __init__(self, host, port):
      self.host = host
      self.port = port
      self.connection = None
   
    def __enter__(self):
      print(f"🔗 连接到数据库 {self.host}:{self.port}")
      self.connection = f"Connection({self.host}:{self.port})"
      return self.connection
   
    def __exit__(self, exc_type, exc_val, exc_tb):
      print(f"🔒 关闭数据库连接")
      self.connection = None
      # 返回True表示异常已被处理,不再传播
      return False

# 使用示例
with DatabaseConnection('localhost', 3306) as conn:
    print(f"执行查询: {conn}")
# 输出:
# 🔗 连接到数据库 localhost:3306
# 执行查询: Connection(localhost:3306)
# 🔒 关闭数据库连接</code></pre>
<h3>方式二:使用 contextlib 装饰器(更简洁)</h3>
<pre><code>from contextlib import contextmanager

@contextmanager
def managed_resource(name):
    print(f"📦 获取资源: {name}")
    resource = f"Resource({name})"
    try:
      yield resource# 这里是 with 语句 as 变量的值
    finally:
      print(f"🗑️ 释放资源: {name}")

# 使用示例
with managed_resource('file_handle') as res:
    print(f"使用: {res}")
# 输出:
# 📦 获取资源: file_handle
# 使用: Resource(file_handle)
# 🗑️ 释放资源: file_handle</code></pre>
<h2>📊 实际应用场景</h2>
<h3>1. 数据库事务管理</h3>
<pre><code>from contextlib import contextmanager

@contextmanager
def transaction(conn):
    try:
      conn.begin()
      yield conn
      conn.commit()
      print("✅ 事务提交成功")
    except Exception as e:
      conn.rollback()
      print(f"❌ 事务回滚: {e}")
      raise

# 使用
with transaction(db_conn) as conn:
    conn.execute("INSERT INTO users VALUES (1, 'Alice')")
    conn.execute("INSERT INTO orders VALUES (1, 100)")</code></pre>
<h3>2. 性能计时器</h3>
<pre><code>import time
from contextlib import contextmanager

@contextmanager
def timer(label):
    start = time.time()
    try:
      yield
    finally:
      elapsed = time.time() - start
      print(f"⏱️ {label}: {elapsed:.4f}秒")

# 使用
with timer("数据处理"):
    result = sum(range(1000000))
# 输出:⏱️ 数据处理: 0.0234秒</code></pre>
<h3>3. 临时修改环境</h3>
<pre><code>import os
from contextlib import contextmanager

@contextmanager
def temporary_env(key, value):
    old_value = os.environ.get(key)
    os.environ = value
    try:
      yield
    finally:
      if old_value is None:
            del os.environ
      else:
            os.environ = old_value

# 使用
with temporary_env('DEBUG', '1'):
    print(f"DEBUG = {os.environ.get('DEBUG')}")# DEBUG = 1
print(f"DEBUG = {os.environ.get('DEBUG')}")# 恢复原值</code></pre>
<h2>🎯 嵌套上下文管理器</h2>
<p>Python支持同时管理多个上下文:</p>
<pre><code># 同时打开多个文件
with open('input.txt') as fin, open('output.txt', 'w') as fout:
    for line in fin:
      fout.write(line.upper())

# 等价于嵌套写法
with open('input.txt') as fin:
    with open('output.txt', 'w') as fout:
      for line in fin:
            fout.write(line.upper())</code></pre>
<h2>💡 最佳实践</h2>
<ul>
<li><strong>资源管理</strong>:文件、网络连接、数据库连接等必须关闭的资源</li>
<li><strong>状态切换</strong>:临时修改配置、切换目录、设置锁等</li>
<li><strong>异常处理</strong>:确保清理代码始终执行,即使在异常情况下</li>
<li><strong>代码简洁</strong>:避免try-finally的嵌套地狱</li>
</ul>
<h2>📝 总结</h2>
<p>上下文管理器是Python中处理资源管理的利器。通过<code>with</code>语句和<code>__enter__</code>/<code>__exit__</code>方法,我们可以:</p>
<ul>
<li>确保资源正确释放,避免泄漏</li>
<li>让代码更加简洁、可读</li>
<li>优雅地处理异常情况</li>
<li>使用<code>contextlib</code>快速创建上下文管理器</li>
</ul>
<p>掌握上下文管理器,让你的Python代码更加Pythonic!</p>
<h2>📚 参考资料</h2>
<ul>
<li>Python官方文档 - 上下文管理器</li>
<li>contextlib 模块文档</li>
<li>PEP 343 - The "with" Statement</li>
</ul>
<hr>
<p><em>本文是Python基础教程系列的一部分,由AI辅助生成。如有错误或建议,欢迎在评论区留言讨论!</em></p><br><br>
来源:https://www.cnblogs.com/cartech/p/19837621
頁: [1]
查看完整版本: 📦 Python上下文管理器:with语句与__enter__/__exit__完全指南