Back to blog

Python Async Programming: Thành Thạo asyncio

pythonasyncioasyncconcurrencyperformance
Python Async Programming: Thành Thạo asyncio

Python Async Programming: Thành Thạo asyncio

Lập trình bất đồng bộ là một trong những kỹ thuật mạnh mẽ nhất để xây dựng ứng dụng Python hiệu suất cao. Với asyncio và cú pháp async/await, bạn có thể xử lý hàng ngàn operations đồng thời một cách hiệu quả—thiết yếu cho web servers, API clients, và các ứng dụng I/O-bound. Hướng dẫn này đưa bạn từ fundamentals đến production-ready patterns.

Những Gì Bạn Sẽ Học

✅ Cú pháp async/await cơ bản
✅ Event loops và cách chúng hoạt động
✅ Coroutines và Tasks
✅ Concurrent operations với asyncio.gather
✅ Async context managers và iterators
✅ Error handling trong async code
✅ Best practices cho async programming
✅ Khi nào dùng async vs threading vs multiprocessing

Điều Kiện Tiên Quyết

Trước khi tìm hiểu async programming, bạn nên hiểu:


Ghi chú: Phần này chứa các ví dụ code tương tự phiên bản tiếng Anh. Để tiết kiệm không gian, chúng tôi tập trung vào giải thích khái niệm bằng tiếng Việt và giữ nguyên code examples.

1. Hiểu Lập Trình Bất Đồng Bộ

Vấn đề: Synchronous code blocks khi chờ I/O operations. Ví dụ: 3 network requests tuần tự mất 6 giây (2s × 3).

Giải pháp: Async programming cho phép start nhiều operations và handle chúng khi complete. Với asyncio.gather(), 3 requests chạy đồng thời chỉ mất ~2 giây (thời gian của operation lâu nhất).

Key Insight: Async không làm individual operations nhanh hơn—nó cho phép làm nhiều operations hơn trong cùng thời gian bằng cách không block khi waiting.

2. Core Concepts

Coroutines: Function định nghĩa với async def. Khi gọi, nó returns coroutine object, không phải result. Phải await hoặc dùng asyncio.run() để get result.

await keyword: Pauses coroutine cho đến khi awaited operation completes. Chỉ dùng được trong async def function.

Event Loop: Core của asyncio - manages tất cả running coroutines, schedules khi chúng run, handles I/O events efficiently. Dùng asyncio.run() để manage event loop (Python 3.10+ best practice).

3. Tasks và Concurrent Execution

Creating Tasks: asyncio.create_task() wraps coroutine và schedules nó run trên event loop. Tasks start immediately khi created.

asyncio.gather(): Runs nhiều coroutines concurrently, returns results theo thứ tự. Perfect cho fetching multiple resources.

asyncio.wait(): More control - cho phép handle completed tasks individually, set return_when conditions.

asyncio.as_completed(): Process results as they arrive (fastest first). Useful khi cần handle results ngay khi ready.

4. Async Context Managers và Iterators

Async Context Managers: Dùng async with cho resources cần async setup/cleanup. Implement __aenter__ và __aexit__ methods. Hoặc dùng @asynccontextmanager decorator từ contextlib.

Async Iterators: Dùng async for để iterate over async data streams. Implement __aiter__ và __anext__ methods. Raise StopAsyncIteration khi done.

Async Generators (Python 3.6+): Dùng async def với yield để create async generators. Useful cho streaming data.

5. Error Handling trong Async Code

Basic try/except: Works bình thường với await. Wrap async calls trong try/except blocks.

gather() với return_exceptions=True: Exceptions được return as results thay vì raised. Allows processing partial results khi some tasks fail.

Task Cancellation: Catch asyncio.CancelledError để cleanup resources. Always re-raise sau khi cleanup.

Timeouts: asyncio.timeout(seconds) (Python 3.11+) hoặc asyncio.wait_for(coro, timeout) cho older versions. Raises TimeoutError khi exceeded.

6. Synchronization Primitives

asyncio.Lock: Prevent race conditions khi multiple coroutines access shared resources. Dùng async with lock:.

asyncio.Semaphore: Limit number of concurrent operations. Ví dụ: Semaphore(3) cho phép max 3 concurrent API calls.

asyncio.Event: Coordinate coroutines với signals. event.set() signals tất cả waiters, await event.wait() blocks until set.

asyncio.Queue: Producer-consumer pattern. await queue.put(item), await queue.get(), queue.task_done(), await queue.join().

7. Real-World Example: Async HTTP Client

Dùng aiohttp library cho async HTTP requests:

  • Create ClientSession với async with
  • Fetch JSON với session.get() và await response.json()
  • Rate limiting với Semaphore + delay

Rate-Limited API Client pattern: Combine Semaphore để limit concurrent requests và delay sau mỗi request để respect rate limits.

8. Async vs Threading vs Multiprocessing

ApproachBest ForGIL AffectedOverhead
asyncioI/O-bound (network, files)Yes, nhưng không matterLow
threadingI/O-bound, C extensionsYesMedium
multiprocessingCPU-bound (calculations)No (separate processes)High

Running Blocking Code trong Async: Dùng loop.run_in_executor() với ThreadPoolExecutor (I/O) hoặc ProcessPoolExecutor (CPU).

9. Best Practices

✅ Do's:

  • Dùng asyncio.run() cho entry point
  • Dùng async context managers cho resources
  • Dùng gather() cho concurrent operations
  • Handle exceptions properly với try/except
  • Dùng timeouts cho network operations
  • Dùng semaphores cho rate limiting

❌ Don'ts:

  • Không dùng time.sleep() trong async code - dùng asyncio.sleep()
  • Không forget await coroutines
  • Không create event loops manually
  • Không mix sync và async không có executor

10. Common Pitfalls

Pitfall 1: Forgetting to await - Coroutine returns coroutine object, không run. Always await!

Pitfall 2: Blocking the Event Loop - Dùng requests library blocks tất cả coroutines. Dùng aiohttp instead.

Pitfall 3: Creating Tasks Without Awaiting - Task might not complete trước khi program ends. Keep reference và await.

Pitfall 4: Not Handling Cancellation - Resources may leak. Dùng try/finally hoặc catch CancelledError để cleanup.

Summary

Trong guide này, bạn đã học:

✅ Async fundamentals: coroutines, await, event loop
✅ Creating và managing Tasks
✅ Concurrent execution với gather(), wait(), as_completed()
✅ Async context managers và iterators
✅ Error handling và timeouts
✅ Synchronization primitives (Lock, Semaphore, Event, Queue)
✅ Khi nào dùng async vs threading vs multiprocessing
✅ Best practices và common pitfalls

Async programming là thiết yếu cho building high-performance Python applications, đặc biệt web servers và API clients. Với FastAPI, async là default và enables handling hàng ngàn concurrent requests efficiently.

Bước Tiếp Theo

Giờ bạn đã hiểu async programming, khám phá các chủ đề liên quan:

Thêm Python Deep Dives:

Áp Dụng Async trong Web Development:

Quay Lại Roadmap:


Thuộc chuỗi bài Lộ Trình Học Python

📬 Đăng ký nhận bản tin

Nhận những bài viết mới nhất qua email mỗi tuần. Không spam, hủy đăng ký bất cứ lúc nào.

Chúng tôi tôn trọng quyền riêng tư của bạn. Hủy đăng ký bất cứ lúc nào.

💬 Comments

Đăng nhập để bình luận

Chúng tôi sẽ không đăng bất cứ điều gì mà không có sự cho phép của bạn.