November 26, 2025
Await, but don’t switch!
Await Is Not a Context Switch: Understanding Python's Coroutines vs. Tasks
Python’s async twist: “await” doesn’t pause, and devs are arguing about it
TLDR: Python’s async model says awaiting a coroutine doesn’t automatically pause; only tasks create real concurrency. Commenters spar over Java’s virtual threads, JS parallels, and lock-happy war stories, turning a subtle concept into a cross-language showdown that matters for writing correct, simpler async code.
Python just dropped a brain-bender: in Python, await doesn’t automatically hand control back—only tasks do. That means you can step into an async function like a normal call until you hit something that truly needs to wait. Cue the comment-section fireworks. Rust folks marched in first, with oersted coolly noting it’s the same vibe in Rust’s tokio world. Then the Java crowd lit the torches: vamega says the article misreads Java’s virtual threads, arguing they use preemptive (the runtime can interrupt you) not cooperative scheduling. Translation: Java doesn’t only pause at obvious wait points.
Meanwhile, a JS dev, pandaxtc, asks the spicy question: wouldn’t the first example behave the same in JavaScript anyway? The thread devolves into a calibration of “what exactly counts as a suspension point” and whether Python is being unfairly framed as quirky when it’s just different. Enter reactordev with a popcorn-worthy “This is gold” and a horror tale about a ‘Python guru’ manager who went lock-happy and turned coroutines into chaos.
For the “just give me tools” crowd, sandblast plugs Effection for JavaScript to mimic Python-style behavior, while pandaxtc tosses a StackOverflow link to sharpen the example game. The meme of the day: “Await isn’t a context switch” — tattooed on forearms and code reviews alike. Verdict: fewer panic locks, more precise mental models, and endless cross-language sniping.
Key Points
- •In Python, awaiting a coroutine does not yield to the event loop; only tasks cause yielding and concurrency.
- •Python separates coroutines (async def) from tasks (asyncio.create_task); the event loop interleaves tasks, not coroutines.
- •In JavaScript and C#, await is always a suspension point, and async functions return Promise or Task/Task<T>, unlike Python.
- •A coroutine executes synchronously until it reaches an awaitable that is not ready (e.g., await asyncio.sleep), preventing interleaving before that point.
- •Concurrency and correct locking should be based on actual suspension points, not merely on functions being async.