Question presented to candidate:
"Explain what actually happens when you write async def and await in Python. What does calling an async function return, what does await do under the hood, and why can one slow line freeze an entire asyncio program?"
What a strong answer should cover:
async defdefines a coroutine function; calling it runs nothing and returns a coroutine object that must be awaited or wrapped in a task, otherwise you getRuntimeWarning: coroutine ... was never awaited.await xworks on any awaitable (a coroutine, aTask, aFuture, or an object with__await__). It suspends the current coroutine and the whole chain of awaiting coroutines up to the driver, which resumes it later withsend(); the return value travels onStopIteration.- Coroutines are built on the same machinery as generators (
RETURN_GENERATOR,SEND,YIELD_VALUEin the bytecode); the event loop is just the code that callssend()at the right time. - Concurrency is cooperative and single-threaded:
awaiton a coroutine runs it to completion sequentially; to overlap work you create tasks (asyncio.create_task,gather,TaskGroup). Nothing runs in parallel. - Any blocking call (
time.sleep,requests.get, CPU-heavy loops) blocks the loop and every task; use async libraries,asyncio.to_thread, or a process pool. - Version facts:
async/awaitsyntax came with PEP 492 in 3.5, became reserved keywords in 3.7, andasyncio.run()was added in 3.7.
Code / implementation expected: Optional β a small asyncio program comparing sequential awaits with gather, or a coroutine driven by hand with send().