如何在Python中使用上下文管理器(with语句)

了解上下文管理器在 Python 中的工作原理。掌握with语句,管理系统资源,并编写自定义上下文管理器。

在编辑器中尝试此解决方案

概述

正确管理外部资源(例如关闭文件句柄、断开数据库连接和释放线程锁)对于构建可靠的生产就绪软件至关重要。未能释放资源可能会导致内存泄漏、文件锁定错误和应用程序挂起。

Python 的“with”语句通过创建上下文管理器来简化资源清理。上下文管理器保证当控制离开块时自动执行清理操作,即使代码抛出异常或提前退出。这消除了对冗长、重复的“try-finally”块的需要。

虽然上下文管理器最常与“open()”等内置操作相关联,但您可以轻松设计自己的自定义上下文管理器。您可以通过创建一个实现“__enter__”和“__exit__”魔术方法的类来构建它们,或者编写一个用“contextlib.contextmanager”装饰器装饰的生成器函数。

代码和执行输出

该脚本演示了使用类实现和 contextlib 装饰器在 Python 中编写自定义上下文管理器。

context_managers.py
在编辑器中尝试
from contextlib import contextmanager

# Method 1: Class-based context manager
class CustomResource:
    def __enter__(self):
        print("[Resource] Opening connection...")
        return self

    def do_work(self):
        print("[Resource] Performing action...")

    def __exit__(self, exc_type, exc_val, exc_tb):
        print("[Resource] Closing connection safely.")
        return False

print("--- Class Context Manager ---")
with CustomResource() as resource:
    resource.do_work()

# Method 2: Generator-based context manager (contextlib)
@contextmanager
def simple_timer():
    print("\n[Timer] Started...")
    try:
        yield
    finally:
        print("[Timer] Finished!")

print("\n--- Decorator Context Manager ---")
with simple_timer():
    print("Performing tasks inside context...")
端子输出
--- Class Context Manager ---
[Resource] Opening connection...
[Resource] Performing action...
[Resource] Closing connection safely.

--- Decorator Context Manager ---

[Timer] Started...
Performing tasks inside context...
[Timer] Finished!

逐步实施

  • 打开文件、数据库或锁时使用with语句来保证资源安全。
  • 使用带有 __enter__ 和 __exit__ 魔术方法的类定义自定义上下文管理器。
  • 在生成器函数上使用 @contextlib.contextmanager 装饰器作为更简单的基于函数的替代方案。
  • 将资源关闭操作放置在清理块内,以确保即使发生错误它们也能运行。

常见问题解答

__exit__ 方法接收哪些参数?

__exit__ 方法接收三个参数,表示异常详细信息(如果引发):exc_type(异常类型)、exc_val(异常值)和 exc_tb(回溯)。如果没有发生错误,则所有三个都将作为 None 传递。

上下文管理器可以抑制异常吗?

是的。如果 __exit__ 方法返回真值(如 True),Python 会抑制异常并在 with 块之后继续执行。如果返回 False,则正常引发异常。

相关主题

推荐的 Python 资源

通过相关的交互式教程、备忘单和代码比较来扩展您的知识。