await, Tasks, and Gathering
Use await, asyncio.create_task, and asyncio.gather for concurrency.
await, Tasks, and Gathering is a free Python Academy lesson on CoddyKit — lesson 2 of 4. You can read the complete lesson below for free — then practise it hands-on in the browser with a built-in code editor and a 24/7 AI tutor. It is part of the Python Academy learning path, one of 4 lessons in the course, and your progress syncs across the web and the CoddyKit app.
await vs Sequential
Using await alone runs coroutines sequentially. To run them concurrently, wrap them in Tasks.
import asyncio
async def main():
# Sequential — total ~3 s
await asyncio.sleep(2)
await asyncio.sleep(1)
# Concurrent using gather — total ~2 s
await asyncio.gather(asyncio.sleep(2), asyncio.sleep(1))asyncio.create_task()
asyncio.create_task(coro) schedules a coroutine to run as an independent Task concurrently with the current coroutine.
import asyncio
async def work(n):
await asyncio.sleep(n)
return n
async def main():
t1 = asyncio.create_task(work(2))
t2 = asyncio.create_task(work(1))
r1 = await t1
r2 = await t2
print(r1, r2) # 2 1 (total ~2 s)
asyncio.run(main())asyncio.gather()
asyncio.gather(*coros) runs coroutines concurrently and returns all results in order when all are complete.
import asyncio
async def fetch(i):
await asyncio.sleep(1)
return f"data-{i}"
async def main():
results = await asyncio.gather(fetch(1), fetch(2), fetch(3))
print(results) # ["data-1", "data-2", "data-3"] in ~1 s
asyncio.run(main())gather with return_exceptions
Set return_exceptions=True so a failed coroutine returns its exception as a result instead of cancelling the whole gather.
import asyncio
async def risky(n):
if n == 2: raise ValueError("bad")
return n
async def main():
results = await asyncio.gather(
risky(1), risky(2), risky(3),
return_exceptions=True
)
print(results) # [1, ValueError("bad"), 3]asyncio.wait()
asyncio.wait(tasks, return_when=...) returns two sets: done and pending. Use FIRST_COMPLETED to react to the first result.
import asyncio
async def slow(): await asyncio.sleep(3); return "slow"
async def fast(): await asyncio.sleep(1); return "fast"
async def main():
tasks = {asyncio.create_task(slow()), asyncio.create_task(fast())}
done, pending = await asyncio.wait(tasks, return_when=asyncio.FIRST_COMPLETED)
for t in pending: t.cancel()Task Cancellation
Call task.cancel() to request cancellation. The task receives asyncio.CancelledError at its next await point.
import asyncio
async def long_job():
try:
await asyncio.sleep(100)
except asyncio.CancelledError:
print("Cancelled!")
raise # re-raise is required
async def main():
t = asyncio.create_task(long_job())
await asyncio.sleep(1)
t.cancel()
await tasyncio.timeout() — Python 3.11+
Wrap an await with asyncio.timeout(seconds) to cancel the operation if it takes too long.
import asyncio
async def main():
try:
async with asyncio.timeout(2):
await asyncio.sleep(10) # too slow
except TimeoutError:
print("Timed out!")asyncio.wait_for()
On Python < 3.11, use asyncio.wait_for(coro, timeout=N) to add a timeout, raising asyncio.TimeoutError.
import asyncio
async def slow(): await asyncio.sleep(5)
async def main():
try:
await asyncio.wait_for(slow(), timeout=2)
except asyncio.TimeoutError:
print("Timed out")Task Names and Inspection
Name tasks for easier debugging with asyncio.create_task(coro, name="...") and inspect with task.get_name().
import asyncio
async def worker(): await asyncio.sleep(1)
async def main():
t = asyncio.create_task(worker(), name="worker-1")
print(t.get_name()) # worker-1
await tTaskGroup — Python 3.11+
asyncio.TaskGroup creates a structured group of tasks. If any task raises, all are cancelled.
import asyncio
async def main():
async with asyncio.TaskGroup() as tg:
t1 = tg.create_task(asyncio.sleep(1))
t2 = tg.create_task(asyncio.sleep(2))
# all tasks done hereSemaphore for Rate Limiting
Use asyncio.Semaphore(n) to limit the number of concurrent operations (e.g., API calls).
import asyncio
sem = asyncio.Semaphore(5) # max 5 concurrent
async def limited_fetch(url):
async with sem:
await fetch(url) # at most 5 at a timeQuick Check
What is the difference between await coro() and asyncio.create_task(coro())?
Recap
Use create_task or gather for concurrent execution. gather collects all results; wait gives fine-grained control. Cancel tasks with .cancel() and apply timeouts with wait_for or asyncio.timeout.
Frequently asked questions
Is the “await, Tasks, and Gathering” lesson free?
Yes — the full text of “await, Tasks, and Gathering” is free to read here on the web, and the Python Academy course includes 4 lessons in total. To practise it interactively (a built-in code editor and a 24/7 AI tutor) and unlock the rest of the Python Academy course, upgrade to CoddyKit PRO.
What will I learn in “await, Tasks, and Gathering”?
Use await, asyncio.create_task, and asyncio.gather for concurrency. You practise Python Academy with hands-on code you run directly in the browser, and a 24/7 AI tutor answers your questions as you work through the lesson.
Do I need any experience to start Python Academy?
No prior experience is required. Python Academy on CoddyKit is structured for beginners through advanced learners; this is — lesson 2 of 4, so you can start here or from the beginning and move at your own pace.
How long does the “await, Tasks, and Gathering” lesson take?
Most CoddyKit lessons take about 5–10 minutes. Each one is bite-sized and interactive, so you make steady progress and pick up exactly where you left off across the web and the app.
Can I write and run code in this Python Academy lesson?
Yes. Every Python Academy lesson includes a built-in code editor, so you write and run real code right in your browser and get instant AI feedback — no local setup required.
All lessons in this course
- Coroutines and the event loop
- await, Tasks, and Gathering
- Async Context Managers and Iterators
- Async I/O Patterns in Production