← Back to Python Course | Chapter 11: Advanced Python | Lesson 7 of 12

Python async & await

What is Asynchronous Programming?

Asynchronous programming lets a single thread juggle many I/O-bound operations -- network calls, file reads, database queries -- without blocking on any one of them. While one task waits on a slow response, Python's event loop switches to run other ready tasks, which is far cheaper than spinning up threads for the same workload.

Example: What is Asynchronous Programming?

python
import asyncio

async def main():
    print("Doing work without blocking a thread")

asyncio.run(main())

Defining Coroutines with async

Prefixing a function definition with async turns it into a coroutine: calling it doesn't run the body immediately, it returns a coroutine object that must be awaited or scheduled to actually execute. This distinction trips up beginners who expect async def functions to behave like regular ones.

Example: Defining Coroutines with async

python
async def greet():
    return "hello"

coro = greet()
print(type(coro))
coro.close()

Awaiting Coroutines with await

The await keyword pauses the current coroutine at that point and hands control back to the event loop until the awaited operation completes, then resumes exactly where it left off. You can only use await inside another async def function -- using it at the top level of ordinary code is a syntax error.

Example: Awaiting Coroutines with await

python
import asyncio

async def get_value():
    await asyncio.sleep(0)
    return 42

async def main():
    value = await get_value()
    print(value)

asyncio.run(main())

Running Coroutines

asyncio.run() is the standard entry point for a synchronous script: it creates a fresh event loop, runs the given coroutine to completion, and cleanly shuts the loop down afterward. It should typically be called only once, at the very top level of your program.

Example: Running Coroutines

python
import asyncio

async def main():
    print("Started with asyncio.run()")

asyncio.run(main())

Running Concurrent Tasks

asyncio.gather() takes multiple coroutines, schedules them to run concurrently on the event loop, and returns their results together once all of them finish. This is how you get real speedup from async code -- awaiting coroutines one after another in sequence gives you no concurrency benefit at all.

Example: Running Concurrent Tasks

python
import asyncio

async def task(n):
    await asyncio.sleep(0)
    return n * 2

async def main():
    results = await asyncio.gather(task(1), task(2), task(3))
    print(results)

asyncio.run(main())

Login to run this code

C/C++/Java/PHP execution requires a free account. Your code is saved — you'll land right back in the editor after logging in.