9.1 上下文管理器
你還記得我們如何使用 運算子 with
來控制資源的訪問嗎?透過它,我們可以精確追蹤
何時資源開始被使用,及該過程何時結束。同樣的事情也可以用於「非同步資源」。
非同步上下文管理器 (AsyncContextManager)
用於非同步程式中的資源管理,確保在
非同步函數中正確地開啟和關閉資源。它們與普通的上下文管理器類似,但專為
非同步函數中的使用而設計,使用關鍵字
async with
。
我不會在這裡詳細解釋,因為你們最近應該不會用到非同步上下文管理器,而等到你們真的需要的時候,應該也會忘了。不過,我還是想讓你們了解這個概念。
創建非同步上下文管理器
非同步上下文管理器透過方法
__aenter__
和 __aexit__
來定義。這些方法類似於普通上下文管理器中的__enter__
和
__exit__
方法,但它們是非同步的。
-
__aenter__()
: 當進入上下文時被調用的非同步方法。 -
__aexit__(exc_type, exc, tb)
: 當退出上下文時被調用的非同步方法。接受三個參數:異常類型、本身和追溯(traceback)
。
創建非同步上下文管理器的範例
import asyncio
class AsyncContextManager:
async def __aenter__(self):
print("進入上下文")
return self
async def __aexit__(self, exc_type, exc, tb):
print("退出上下文")
async def main():
async with AsyncContextManager():
print("在上下文內")
asyncio.run(main())
這個代碼將會這樣執行:
- 非同步地啟動函數
main()
- 函數
main()
開始執行 - 創建一個
AsyncContextManager
型別的對象 - 調用對象
AsyncContextManager
的方法__aenter__()
- 輸出
print("進入上下文")
- 執行代碼
print("在上下文內")
- 調用對象
AsyncContextManager
的方法__aexit__()
- 結束函數
main()
的執行
9.2 使用範例
在上面的範例中,不一定要使用非同步版本的上下文管理器——即使它同步,代碼也能正常運行。
但是需要非同步的管理器,當在區塊內
with
調用非同步函數或者
使用運算子
await
。
用於文件操作的非同步上下文管理器
在這個範例中使用了 aiofiles
庫來進行非同步的文件讀取和寫入。非同步上下文管理器 aiofiles.open
允許
在非同步上下文中安全地開啟和關閉文件。
import aiofiles
import asyncio
async def main():
async with aiofiles.open('example.txt', mode='w') as file:
await file.write('Hello, world!')
asyncio.run(main())
用於網路操作的非同步上下文管理器
在這個範例中使用了 aiohttp
庫來進行非同步的 HTTP 請求。非同步上下文管理器 ClientSession
和 session.get
確保正確的連接管理。
import aiohttp
import asyncio
async def fetch(url):
async with aiohttp.ClientSession() as session:
async with session.get(url) as response:
return await response.text()
async def main():
html = await fetch('https://example.com')
print(html)
asyncio.run(main())
非同步上下文管理器提供了資源的自動管理,例如文件、網路連接以及其他需要開啟和關閉的資源。
方法 __aenter__
和 __aexit__
允許在進入和退出上下文時執行非同步操作,確保任務的平行執行。
使用非同步上下文管理器有助於避免資源洩漏並保證所有資源都能夠正確釋放。
GO TO FULL VERSION