async, await, tasks, and gather
async, await, tasks, and gather
Four words carry all of asyncio. async def declares a function whose body can pause. Calling it does not run it; it returns a coroutine object, a description of work that has not started. await runs a coroutine and pauses the caller until it finishes, handing the event loop control in the meantime. A task is a coroutine that the loop has been told to run on its own, so it progresses whether or not anyone is currently awaiting it. And gather takes several coroutines, wraps each in a task, and waits for all of them.
The event loop is the scheduler underneath. asyncio.run(main()) creates one, runs main until it completes, and shuts the loop down. Inside, every await on something that is genuinely waiting, a socket, a sleep, another task, is a point where the loop can switch to something else. Everything between awaits runs to completion without interruption, which is why async code needs no locks for ordinary data structures.
Continue reading
Pro unlocks every video lesson, the full notes and runnable code across the Python with AI course, from the language itself to agents, MCP, Langfuse and deployment.