asyncio Python: How to Use Async/Await for Asynchronous Code

Online Python Trainer for Beginners

Learn Python easily without overwhelming theory. Solve practical tasks with automatic checking, get hints in Russian, and write code directly in your browser — no installation required.

Start Course

What Is Asynchronous Programming and Why You Need It

Asynchronous programming lets you run multiple operations at the same time without waiting for each one to finish. This is critical for building high-performance applications that don't freeze during slow operations.

Key Benefits of Async

Async programming shines in these scenarios:

  • Network requests (HTTP requests, working with REST APIs)
  • File system operations (reading and writing large files)
  • Database interactions (SQL queries, NoSQL operations)
  • WebSocket connections and real-time applications
  • Web scraping and data extraction
  • Message queue processing

Introduction to the asyncio Library

asyncio is Python's standard library for writing asynchronous code based on an event loop. It's been part of Python since version 3.4 and received major improvements in versions 3.7+.

Key Features of asyncio

With asyncio you can:

  • Create and manage coroutines
  • Run multiple async tasks in parallel
  • Efficiently handle thousands of simultaneous connections
  • Integrate with async libraries and frameworks

Core asyncio Concepts

Coroutines

A coroutine is a special function that can be paused and later resumed. In Python, coroutines are defined using the async def keyword.

import asyncio

async def greet():
    print("Hello!")
    await asyncio.sleep(1)
    print("1 second has passed.")

# Running a coroutine
asyncio.run(greet())

The await Keyword

await is used to pause a coroutine's execution until another async operation completes. This is the key mechanism for handing control back to the event loop.

async def delayed_message():
    print("Starting execution")
    await asyncio.sleep(2)
    print("Message after 2 seconds")

asyncio.run(delayed_message())

The Event Loop

The event loop is the heart of asyncio — the mechanism that manages the execution of all async tasks. Starting with Python 3.7, it's recommended to use asyncio.run() to launch async code.

# Modern approach (Python 3.7+)
asyncio.run(main_coroutine())

# Legacy approach (before Python 3.7)
loop = asyncio.get_event_loop()
loop.run_until_complete(main_coroutine())

Creating and Managing Async Tasks

Running Tasks in Parallel

Async code really shines when you run multiple tasks in parallel:

async def task(name, delay):
    print(f"Task {name} started")
    await asyncio.sleep(delay)
    print(f"Task {name} finished after {delay} seconds")
    return f"Result from {name}"

async def main():
    # Method 1: asyncio.gather()
    results = await asyncio.gather(
        task("A", 2),
        task("B", 1),
        task("C", 3)
    )
    print("All results:", results)

asyncio.run(main())

Creating Tasks with asyncio.create_task()

For finer control over execution, use asyncio.create_task():

async def main():
    # Create tasks
    task_a = asyncio.create_task(task("A", 2))
    task_b = asyncio.create_task(task("B", 1))
    task_c = asyncio.create_task(task("C", 3))
    
    # Wait for them to finish
    await task_a
    await task_b
    await task_c

asyncio.run(main())

Async HTTP Requests

Installation and Usage

Blogs

Book Recommendations