Cả hai đều thực hiện timeout bằng cơ chế huỷ (cancellation): hết hạn thì task bị cancel(), coroutine nhận CancelledError tại điểm await gần nhất, rồi lời gọi bên ngoài thấy TimeoutError.
asyncio.wait_for(coro, timeout): bọc một awaitable, có từ lâu.async with asyncio.timeout(seconds)(Python 3.11+): context manager, đặt hạn cho cả khối gồm nhiềuawait; có bảntimeout_attheo mốc thời gian và cho phép dời hạn quareschedule().
try:
async with asyncio.timeout(3):
data = await client.get(url)
await store(data) # both awaits share the 3s budget
except TimeoutError:
logger.warning("upstream timed out")Hai luật khi làm việc với cancellation:
- Không nuốt CancelledError. Nếu bắt để dọn dẹp thì phải raise lại, nếu không asyncio.timeout sẽ hoạt động sai và task tiếp tục chạy ngoài kiểm soát. Trường hợp thật sự muốn chặn huỷ thì phải gọi thêm uncancel().
- Huỷ không tức thời. Task chỉ dừng khi chạm điểm await tiếp theo; một vòng lặp CPU thuần sẽ chạy hết rồi mới dừng. Dọn tài nguyên đặt trong finally hoặc dùng async with để chắc chắn được giải phóng.
Cần bảo vệ một đoạn không được huỷ giữa chừng (ví dụ ghi bản ghi bù trừ) thì bọc bằng asyncio.shield, nhưng dùng dè dặt vì nó phá cơ chế timeout của tầng trên.