第21天:上下文管理器
課程簡介
上下文管理器(Context Manager)是一種用於管理資源的工具,特別適合需要進行資源分配和釋放的場景,例如檔案操作、資料庫連線等。上下文管理器確保在進入和退出時,資源能夠被自動處理,無需開發者手動進行。Python 提供了兩種使用上下文管理器的方式:一是使用 with
語句,二是定義自訂的上下文管理器。今天我們將學習如何使用內建和自訂的上下文管理器。
學習內容
1. 使用 with
語句
with
語句是使用上下文管理器的最常見方式,它會自動處理進入上下文和退出上下文時需要的操作。最常見的例子就是檔案操作。
範例:
1
2
3
with open('example.txt', 'r') as file:
content = file.read()
print(content)
這段程式碼自動處理了檔案的開啟和關閉,無需明確調用 file.close()
,即使程式發生異常,檔案也會自動關閉。
2. 自訂上下文管理器:__enter__
和 __exit__
我們可以定義自己的上下文管理器,透過實作兩個特殊方法:__enter__()
和 __exit__()
。
__enter__()
:在進入上下文時執行的邏輯,返回值會賦給with
語句中的變數。__exit__()
:在離開上下文時執行的邏輯,通常用來進行資源釋放,例如關閉檔案或釋放資料庫連線。
範例:
1
2
3
4
5
6
7
8
9
10
class MyContextManager:
def __enter__(self):
print("進入上下文")
return self
def __exit__(self, exc_type, exc_val, exc_tb):
print("退出上下文")
with MyContextManager() as manager:
print("在上下文中執行")
輸出結果:
1
2
3
進入上下文
在上下文中執行
退出上下文
在這個範例中,我們自訂了一個上下文管理器,在進入和退出上下文時分別執行相應的邏輯。
3. 上下文管理器的應用場景
上下文管理器廣泛應用於各種需要資源管理的場景:
- 檔案處理:確保檔案能夠正確地開啟與關閉。
- 資料庫連線:自動開啟和關閉資料庫連線,避免資源洩漏。
- 線程鎖:在多線程環境下,自動獲取和釋放鎖。
- 網路連線:確保連線能夠在使用後正確關閉。
4. 使用 contextlib
模組
Python 的 contextlib
模組提供了幾個輔助工具來簡化上下文管理器的創建過程。
4.1 使用 contextlib.contextmanager
裝飾器
contextlib.contextmanager
可以將一個普通的生成器函數轉換為上下文管理器。這比實作 __enter__
和 __exit__
更簡單。
範例:
1
2
3
4
5
6
7
8
9
10
from contextlib import contextmanager
@contextmanager
def my_manager():
print("進入上下文")
yield
print("退出上下文")
with my_manager():
print("在上下文中執行")
輸出結果:
1
2
3
進入上下文
在上下文中執行
退出上下文
在這裡,my_manager
函數使用 @contextmanager
裝飾器,將它轉換成一個上下文管理器。yield
分隔了進入上下文和退出上下文的行為。
5. 處理異常情況
上下文管理器中的 __exit__()
方法可以用來處理異常。它接收三個參數:
exc_type
:異常的類型。exc_val
:異常的具體值。exc_tb
:異常的追蹤信息(traceback)。
如果 __exit__()
返回 True
,異常會被上下文管理器吞掉,否則異常會被重新拋出。
範例:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
class ErrorHandlingContextManager:
def __enter__(self):
print("進入上下文")
return self
def __exit__(self, exc_type, exc_val, exc_tb):
if exc_type:
print(f"捕捉到異常: {exc_val}")
return True # 異常被處理
print("正常退出上下文")
with ErrorHandlingContextManager():
print("在上下文中執行")
raise ValueError("這是一個異常")
輸出結果:
1
2
3
進入上下文
在上下文中執行
捕捉到異常: 這是一個異常
這段程式碼中,當發生異常時,__exit__()
捕捉到異常並返回 True
,因此異常不會被拋出。
教學重點
with
語句:學會如何使用with
語句來自動管理資源。- 自訂上下文管理器:理解如何實作
__enter__
和__exit__
方法,來創建自訂的上下文管理器。 contextlib
模組:學會使用contextlib.contextmanager
來簡化上下文管理器的創建。- 異常處理:理解如何在上下文管理器中捕捉和處理異常情況。
任務
- 使用
with
語句開啟一個檔案,讀取其中的內容並打印。 - 定義一個自訂的上下文管理器
TimerContext
,用於計算程式塊的執行時間。 - 使用
@contextmanager
創建一個上下文管理器,用於模擬資料庫連線的開啟和關閉。 - 修改上下文管理器,讓它能夠捕捉異常,並在發生異常時記錄錯誤訊息。