An asyncio task is a future-like unit of work that wraps a coroutine and schedules it on the event loop. Creating a task returns immediately, allowing other code to run while the coroutine waits for I/O; awaiting the task later retrieves its result or raises its exception. section 2.3 section 2.5.2
Use tasks when independent long-running operations should progress concurrently:
- Create one with asyncio.create_task(coroutine); the task is scheduled to run as soon as possible. section 2.3.1
- Create several tasks before awaiting them so their I/O waits overlap rather than running sequentially. section 2.3.2
- Await tasks at an appropriate point to obtain results, observe exceptions, and prevent them from being discarded during event-loop shutdown. section 2.3.1 section 3.5.3
- Cancel tasks or apply asyncio.wait_for when network operations may run indefinitely. section 2.4
Running delays concurrently
Create three tasks with asyncio.create_task(delay(3)), then await each task. Their waiting periods overlap, so the program completes in about three seconds rather than just over nine. Code that does not wait on I/O does not become parallel: the event loop remains single-threaded and switches between tasks when they suspend. section 2.3.2 section 1.3.3
One task per echo-server connection
A listening coroutine can accept connections sequentially while creating an echo task for each client. Each task awaits socket reads and writes, preventing one client’s wait from blocking other clients. If an echo task raises an exception, await it or handle the exception inside the task so failure and cleanup are visible. section 3.5.2 section 3.5.3
Listing 2.8 Creating a task
import asyncio
from util import delay
async def main():
sleep_for_three = asyncio.create_task(delay(3))
print(type(sleep_for_three))
result = await sleep_for_three
print(result)
asyncio.run(main())
Inspect the minimal create_task example showing immediate task creation, type distinction, and later result retrieval. section 2.3.1









