如何在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 資源

透過相關的互動式教學、備忘單和程式碼比較來擴展您的知識。