How to Run Coroutines Concurrently with asyncio.gather in Python

Run multiple async coroutines concurrently and collect their results in the order they were passed.

Medium Python 3.7+ Aug 9, 2026 Concurrency & performance 15 views 0 copies

Python code

22 lines
Python 3.7+
import asyncio


async def fetch_data(name: str, delay: float) -> str:
    """Simulate an async operation (e.g., API call) with a delay."""
    await asyncio.sleep(delay)
    return f"{name} data (after {delay}s)"


async def main() -> None:
    """Run multiple coroutines concurrently with asyncio.gather."""
    results = await asyncio.gather(
        fetch_data("alpha", 2.0),
        fetch_data("beta", 1.0),
        fetch_data("gamma", 1.5),
    )
    for item in results:
        print(item)


if __name__ == "__main__":
    asyncio.run(main())

Output

stdout
alpha data (after 2.0s)
beta data (after 1.0s)
gamma data (after 1.5s)

How it works

asyncio.gather schedules all coroutines concurrently on the event loop, then awaits them together. The returned list preserves the original call order, not completion order — alpha finishes last but appears first. Each fetch_data coroutine suspends on asyncio.sleep, letting the loop switch to another coroutine. asyncio.run(main()) creates and closes the event loop for the whole program. This pattern cuts total wall time from ~4.5 seconds to ~2 seconds versus running sequentially.

Common mistakes

  • Forgetting `await` before `asyncio.gather(...)`, which wraps a coroutine without running it
  • Expecting results in completion order instead of call order
  • Passing a list directly (`*my_list` needed to unpack coroutines)
  • Ignoring the `return_exceptions=True` option when one task may fail

Variations

  1. Use `asyncio.gather(*[fetch_data(n, d) for n, d in jobs])` with a list of coroutines
  2. Switch to `asyncio.wait` or `asyncio.as_completed` when you need fine-grained control over results

Real-world use cases

  • Batching independent API or database calls — fetch a user's profile, orders, and preferences in parallel.
  • Fanning out HTTP requests to multiple third-party endpoints and combining their responses for one aggregated view.
  • Running parallel health checks across several microservices and reporting results in a consistent order.

Sponsored

Run this sample

Open the browser IDE to tweak the example and see results without installing anything.

Open editor

More from Concurrency & performance

Related tutorials and quizzes for this topic.