asyncio is a standard Python library for writing concurrent code using async/await syntax. In this article, we will look at practical usage scenarios.

When should you use asyncio?

asyncio is a great fit for I/O-bound tasks: HTTP requests, database operations, and file I/O. If your code spends most of its time waiting for network or disk responses, asyncio can provide a significant performance boost.

For CPU-bound tasks (heavy computations, data processing), multiprocessing is usually a better choice.

Basic example

import asyncio
import aiohttp

async def fetch(session, url):
    async with session.get(url) as response:
        return await response.text()

async def main():
    urls = ["https://example.com", "https://python.org"]
    async with aiohttp.ClientSession() as session:
        tasks = [fetch(session, url) for url in urls]
        results = await asyncio.gather(*tasks)
    return results

asyncio.run(main())

Key concepts

  • async def — defines a coroutine. Calling a coroutine does not execute it immediately.
  • await — pauses the current coroutine until the awaited result is ready.
  • asyncio.gather() — runs multiple coroutines concurrently and waits for all of them.
  • asyncio.create_task() — schedules a coroutine to run in the background without waiting immediately.

Integration with web frameworks

FastAPI has native async/await support. Flask 2.x also supports async views, but requires installing flask[async].

Practical advice

Do not mix synchronous and asynchronous code unless necessary. If you use a sync library inside asyncio, wrap the call with loop.run_in_executor() to avoid blocking the event loop.