An async function (coroutine) is a function that can pause execution and yield control back to the event loop while waiting for I/O. The event loop runs multiple coroutines concurrently by switching between them whenever one is paused. That is asyncio.
The practical patterns: use async def and await for all I/O operations. Use asyncio.gather() to run multiple I/O operations concurrently. Use asyncio.create_task() to start a coroutine without waiting for it.
CPU-bound work belongs in a ThreadPoolExecutor, not in a coroutine. Asyncio does not make CPU work concurrent — only I/O.
Understanding this boundary eliminates 80% of asyncio confusion.
— Dick Bassey | DevDick | 2023