Python 简明教程

Python - Context Managers

Context managers 在 Python 中提供了一种有效管理资源安全性的强有力方式。Python 中的 context manager 是一个对象,它为 with 语句的使用定义了一个运行时上下文。它确保自动执行设置和清除操作。

Context managers in Python provide a powerful way to manage resources efficiently and safely. A context manager in Python is an object that defines a runtime context for use with the with statement. It ensures that setup and cleanup operations are performed automatically.

例如,当处理文件操作时,上下文管理器处理文件的打开和关闭,确保正确管理资源。

For instance, when working with file operations, context managers handle the opening and closing of files, ensuring that resources are managed correctly.

How Context Managers Work?

Python 上下文管理器通过实现 enter()exit() 方法(或它们的异步操作的异步等效项)来工作。这些方法确保正确获取和释放资源。此外,Python 的 contextlib 模块进一步简化了自定义上下文管理器的创建。

Python context managers work by implementing the enter() and exit() methods (or their asynchronous equivalents for async operations). These methods ensure that resources are correctly acquired and released. Also, Python’s contextlib module further simplifies the creation of custom context managers.

Example

以下是一个简单的示例,展示了上下文管理器如何在 Python 中处理文件操作。

Here’s a simple example demonstrating how a context manager works with file operations in Python.

with open('example.txt', 'w') as file:
    file.write('Hello, Tutorialspoint!')

在此示例中,已在写模式下打开一个文件,当 with 语句内的块被退出时自动关闭。

In this example, a file is opened in the write mode, and then automatically closed when the block inside the with statement is exited.

Python Context Manager Types

Python 支持同步和异步上下文管理器。每种类型都有用于管理上下文生命周期的特定方法。

Python supports both synchronous and asynchronous context managers. Each type has specific methods that need to be implemented to manage the life cycle of the context.

Synchronous Context Managers

同步上下文管理器使用 enter()exit() 方法实现。

A synchronous context managers are implemented using the enter() and exit() methods.

当执行进入 with 语句的上下文时,将调用 enter(self) 方法。此方法应返回将在 with 块中使用的资源。

The enter(self) method is called when execution enters the context of the with statement. This method should return the resource to be used within the with block.

Example

下面是一个使用 enter () 和 exit () 方法创建我们自己的上下文管理器的简单示例。

Here is a simple example of creating our own context manager using the enter() and exit() methods.

class MyContextManager:
   def __enter__(self):
      print("Entering the context")
      return self

   def __exit__(self, exc_type, exc_value, traceback):
      print("Exiting the context")

with MyContextManager():
   print("body")

执行上述代码后,您将获得以下 output

On executing the above code you will get the following output

Entering the context
body
Exiting the context

当执行离开 with 语句的上下文时,将调用 exit(self, exc_type, exc_value, traceback) 方法。它可以在发生任何异常时处理这些异常,它返回一个布尔标志,指示是否应禁止该异常。

The exit(self, exc_type, exc_value, traceback) method is called when execution leaves the context of the with statement. It can handle exceptions if any occur, and it returns a Boolean flag indicating if the exception should be suppressed.

此示例演示了如何创建我们自己的上下文管理器以及 exit () 方法如何处理异常。

This example demonstrates creating the our own context manager and how the exit() methods handle exceptions.

class MyContextManager:
   def __enter__(self):
      print("Entering the context")
      return self

   def __exit__(self, exc_type, exc_value, traceback):
      print("Exiting the context")
      if exc_type:
         print("An exception occurred")
      return True  # Suppress exception

with MyContextManager():
   print("body")
   name =  "Python"/3 #to raise an exception

执行上述代码后,您将获得以下 output

While executing the above code you will get the following output

Entering the context
body
Exiting the context
An exception occurred

Asynchronous Context Managers

与同步上下文管理器类似,异步上下文管理器也使用 aenter () 和 aexit () 这两个方法实现。它们用在 async with 语句中。

Similar to the synchronous context managers, Asynchronous context managers are also implemented using the two methods which are aenter() and aexit(). These are used within async with statements.

The aenter(self) Method − 它必须返回一个在进入上下文时将等待的 awaitable。

The aenter(self) Method − It must return an awaitable that will be awaited when entering the context.

aexit(self, exc_type, exc_value, traceback) Method − 它必须返回一个在退出上下文时将等待的 awaitable。

aexit(self, exc_type, exc_value, traceback) Method − It must return an awaitable that will be awaited when exiting the context.

Example

下面是创建异步上下文管理器类的示例 −

Following is the example of creating an asynchronous context manager class −

import asyncio
class AsyncContextManager:
   async def __aenter__(self):
      print("Entering the async context class")
      return self

   async def __aexit__(self, exc_type, exc_value, traceback):
      print("Exiting the async context class")
      if exc_type:
         print("Exception occurred")
      return True

async def main():
   async with AsyncContextManager():
      print("Inside the async context")
      name =  "Python"/3 #to raise an exception

asyncio.run(main())

执行上述代码时,您将获得以下输出 -

On executing the above code you will get the following output −

Entering the async context class
Inside the async context
Exiting the async context class
Exception occurred

Creating Custom Context Managers

Python 标准库中的 contextlib 模块提供了更轻松地创建上下文管理器的工具。

The contextlib module from the Python standard library provides the utilities to create context managers more easily.

Using the contextlib.contextmanager() Function

contextlib.contextmanager() 函数是一个装饰器,它允许你为 with 语句上下文管理器创建工厂函数。它无需定义一个单独的类或单独实现 enter()exit() 方法。

The contextlib.contextmanager() function is a decorator allows you to create factory functions for with statement context managers. It eliminates the need to define a separate class or implement the enter() and exit() methods individually.

Example

下面是一个使用 contextlib.contextmanager 来创建上下文管理器函数的示例。

Here’s an example using the contextlib.contextmanager to create a context manager function.

from contextlib import contextmanager

@contextmanager
def my_context_manager():
   print("Entering the context manager method")
   try:
      yield
   finally:
      print("Exiting the context manager method")

with my_context_manager():
   print("Inside the context")

执行上述代码时,您将获得以下输出 -

On executing the above code you will get the following output −

Entering the context manager method
Inside the context
Exiting the context manager method

Using the contextlib.asynccontextmanager() Function

contextlib 模块还提供了专门为创建异步上下文管理器设计的 asynccontextmanager。它与 contextmanager 类似,无需分别定义一个单独的类或实现 aenter()aexit() 方法。

The contextlib module also provides asynccontextmanager, specifically designed for creating asynchronous context managers. It is similar to contextmanager and eliminates the need to define a separate class or implement the aenter() and aexit() methods individually.

Example

下面是一个演示如何使用 contextlib.asynccontextmanager() 来创建异步上下文管理器函数的示例。

Here’s an example demonstrating the usage of contextlib.asynccontextmanager() to create an asynchronous context manager function.

import asyncio
from contextlib import asynccontextmanager

@asynccontextmanager
async def async_context_manager():
   try:
      print("Entering the async context")
      # Perform async setup tasks if needed
      yield
   finally:
      # Perform async cleanup tasks if needed
      print("Exiting the async context")

async def main():
   async with async_context_manager():
      print("Inside the async context")
      await asyncio.sleep(1)  # Simulating an async operation

# Run the asyncio event loop
asyncio.run(main())

执行上述代码时,您将获得以下输出 -

On executing the above code you will get the following output −

Entering the async context
Inside the async context
Exiting the async context