Python - 上下文管理器



Python 中的上下文管理器提供了一種強大且安全的方式來有效管理資源。Python 中的上下文管理器是一個物件,它定義了一個與with語句一起使用的執行時上下文。它確保自動執行設定和清理操作。

例如,在處理檔案操作時,上下文管理器會處理檔案的開啟和關閉,確保正確管理資源。

上下文管理器的工作原理?

Python 上下文管理器透過實現__enter__()__exit__()方法(或非同步操作的非同步等效方法)來工作。這些方法確保正確獲取和釋放資源。此外,Python 的contextlib模組進一步簡化了自定義上下文管理器的建立。

示例

以下是一個簡單的示例,演示了上下文管理器如何在 Python 中與檔案操作一起工作。

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

在此示例中,檔案以寫入模式開啟,然後在退出with語句內的程式碼塊時自動關閉。

Python 上下文管理器型別

Python 支援同步和非同步上下文管理器。每種型別都有需要實現的特定方法來管理上下文的生命週期。

同步上下文管理器

同步上下文管理器使用__enter__()__exit__()方法實現。

1. __enter__() 方法

當執行進入 with 語句的上下文時,將呼叫__enter__(self)方法。此方法應返回要在 with 程式碼塊內使用的資源。

示例

以下是如何使用__enter__()__exit__()方法建立我們自己的上下文管理器的簡單示例。

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")

執行以上程式碼,您將得到以下輸出 -

Entering the context
body
Exiting the context

2. __exit__() 方法

__exit__(self, exc_type, exc_value, traceback) 方法在執行離開 with 語句上下文時被呼叫。它可以處理任何發生的異常,並返回一個布林標誌,指示是否應該抑制異常。

此示例演示瞭如何建立我們自己的上下文管理器以及 __exit__() 方法如何處理異常。

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

在執行以上程式碼時,您將獲得以下輸出 -

Entering the context
body
Exiting the context
An exception occurred

非同步上下文管理器

與同步上下文管理器類似,非同步上下文管理器也使用兩個方法實現,即 __aenter__()__aexit__()。這些用於async with 語句中。

__aenter__(self) 方法 - 它必須返回一個可等待物件,當進入上下文時將被等待。

__aexit__(self, exc_type, exc_value, traceback) 方法 - 它必須返回一個可等待物件,當退出上下文時將被等待。

示例

以下是建立非同步上下文管理器類的示例 -

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())

執行以上程式碼,您將獲得以下輸出 -

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

建立自定義上下文管理器

Python 標準庫中的contextlib 模組提供了更輕鬆地建立上下文管理器的實用程式。

使用 contextlib.contextmanager() 函式

contextlib.contextmanager() 函式是一個裝飾器,允許您為 with 語句上下文管理器建立工廠函式。它消除了定義單獨的類或分別實現__enter__()__exit__() 方法的需要。

示例

這是一個使用 contextlib.contextmanager 建立上下文管理器函式的示例。

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")

執行以上程式碼,您將獲得以下輸出 -

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

使用 contextlib.asynccontextmanager() 函式

contextlib 模組還提供 asynccontextmanager,專門用於建立非同步上下文管理器。它類似於 contextmanager,並且消除了定義單獨的類或分別實現__aenter__()__aexit__() 方法的需要。

示例

這是一個演示使用 contextlib.asynccontextmanager() 建立非同步上下文管理器函式的示例。

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())

執行以上程式碼,您將獲得以下輸出 -

Entering the async context
Inside the async context
Exiting the async context
廣告