9.1 Context Manager
Bạn nhớ cách chúng ta dùng từ khóa with để điều khiển quyền truy cập vào tài nguyên không? Nhờ nó mà có thể theo dõi chính xác, khi nào tài nguyên bắt đầu được sử dụng và khi nào quá trình này kết thúc. Điều tương tự cũng có thể làm với "tài nguyên bất đồng bộ".
Async Context Manager được sử dụng để quản lý tài nguyên trong lập trình bất đồng bộ, đảm bảo mở và đóng tài nguyên đúng cách trong các hàm async. Chúng hoạt động tương tự như các context manager thông thường, nhưng dành cho việc sử dụng trong các hàm async với từ khóa async with.
Mình sẽ không đi sâu phân tích cái này, vì trong thời gian gần, bạn chắc chắn không tạo ra Async Context Manager của riêng mình đâu, và đến lúc bạn quyết định làm điều này, thì có khi bạn cũng quên hết rồi. Nhưng mình muốn giới thiệu cho bạn về khái niệm này.
Tạo Async Context Manager
Async Context Manager được định nghĩa bằng cách sử dụng các phương thức __aenter__ và __aexit__. Các phương thức này tương tự như các phương thức __enter__ và __exit__ trong context manager thông thường, nhưng là bất đồng bộ.
-
__aenter__(): Phương thức async, được gọi khi vào context. -
__aexit__(exc_type, exc, tb): Phương thức async, được gọi khi thoát context. Nhận ba tham số: loại ngoại lệ, chính ngoại lệ và traceback.
Ví dụ tạo Async Context Manager
import asyncio
class AsyncContextManager:
async def __aenter__(self):
print("Vào context")
return self
async def __aexit__(self, exc_type, exc, tb):
print("Thoát context")
async def main():
async with AsyncContextManager():
print("Bên trong context")
asyncio.run(main())
Đây là cách mà mã trên sẽ được thực thi:
- Hàm async
main()chạy - Hàm
main()bắt đầu thực hiện - Tạo đối tượng kiểu
AsyncContextManager - Phương thức
__aenter__()của đối tượngAsyncContextManagerđược gọi - Xuất ra
print("Vào context") - Thực thi mã
print("Bên trong context") - Phương thức
__aexit__()của đối tượngAsyncContextManagerđược gọi - Hàm
main()kết thúc
9.2 Ví dụ sử dụng
Trong ví dụ trên, không nhất thiết phải sử dụng phiên bản async của context manager — mã vẫn chạy, ngay cả khi bạn làm cho nó đồng bộ.
Nhưng bạn cần async manager khi bên trong block with gọi hàm async hoặc sử dụng từ khóa await.
Async Context Manager cho thao tác với file
Ví dụ này sử dụng thư viện aiofiles để đọc và ghi file bất đồng bộ. Async Context Manager aiofiles.open cho phép mở và đóng file một cách an toàn trong context bất đồng bộ.
import aiofiles
import asyncio
async def main():
async with aiofiles.open('example.txt', mode='w') as file:
await file.write('Chào, thế giới!')
asyncio.run(main())
Async Context Manager cho các hoạt động mạng
Ví dụ này sử dụng thư viện aiohttp để thực hiện các HTTP request bất đồng bộ. Async Context Manager ClientSession và session.get đảm bảo quản lý kết nối đúng cách.
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())
Async Context Manager đảm bảo quản lý tài nguyên tự động, chẳng hạn như file, kết nối mạng và các tài nguyên khác cần phải mở và đóng.
Các phương thức __aenter__ và __aexit__ cho phép thực hiện các thao tác async khi vào và ra khỏi context, đảm bảo thực thi tác vụ song song. Sử dụng Async Context Manager giúp tránh rò rỉ tài nguyên và đảm bảo tất cả các tài nguyên được giải phóng đúng cách.
GO TO FULL VERSION