await Is Not a Context Switch: Understanding Python's Coroutines vs Tasks
Blog post from Mergify
Python's async model is often misunderstood, particularly by engineers familiar with JavaScript or C#, where "await" always indicates a suspension point allowing the event loop to take control. In Python, however, the distinction between coroutines and tasks is crucial; coroutines are synchronous unless they reach a suspension point, while tasks introduce concurrency. This misunderstanding can lead to unnecessary locking and complexity in async code. The key difference is that awaiting a coroutine does not yield control back to the event loop, unlike tasks which do. This design choice stems from Python's evolution from generators, providing explicit boundaries between structured control flow and concurrency. Understanding this distinction helps developers manage concurrency effectively by recognizing where actual suspension points occur, thereby avoiding redundant locks and focusing on genuine concurrency boundaries.