asyncio.wait() and Task Control
Stryg for at vise menuen
asyncio.gather() is convenient but opinionated – it waits for all coroutines and returns results in input order. asyncio.wait() gives you more control: you decide when to stop waiting and what to do with each task individually.
Basic Usage
asyncio.wait() takes a set of tasks (not coroutines) and returns two sets: done and pending.
12345678910111213141516171819202122232425import asyncio import httpx import nest_asyncio nest_asyncio.apply() # Fetching posts and processing them as they complete async def fetch_post(client, post_id): url = f"https://jsonplaceholder.typicode.com/posts/{post_id}" response = await client.get(url) return response.json()["title"] async def main(): async with httpx.AsyncClient() as client: tasks = { asyncio.create_task(fetch_post(client, post_id)) for post_id in [1, 2, 3] } done, pending = await asyncio.wait(tasks) for task in done: print(task.result()) asyncio.run(main())
Unlike gather(), results arrive in completion order – whichever task finishes first is processed first.
Return Conditions
The return_when parameter controls when wait() returns:
asyncio.ALL_COMPLETED(default): waits for all tasks to finish;asyncio.FIRST_COMPLETED: returns as soon as any one task finishes;asyncio.FIRST_EXCEPTION: returns as soon as any task raises an exception.
1234567891011121314151617181920212223242526272829303132import asyncio import httpx import nest_asyncio nest_asyncio.apply() # Returning as soon as the first post is fetched async def fetch_post(client, post_id): url = f"https://jsonplaceholder.typicode.com/posts/{post_id}" response = await client.get(url) return response.json()["title"] async def main(): async with httpx.AsyncClient() as client: tasks = { asyncio.create_task(fetch_post(client, post_id)) for post_id in [1, 2, 3] } done, pending = await asyncio.wait( tasks, return_when=asyncio.FIRST_COMPLETED, ) print(f"First result: {next(iter(done)).result()}") print(f"Still pending: {len(pending)} tasks") # Cancelling remaining tasks for task in pending: task.cancel() asyncio.run(main())
Cancelling Tasks
Any task can be cancelled with task.cancel(). The task receives a CancelledError at its next await point.
1234567891011121314151617181920212223242526import asyncio import nest_asyncio nest_asyncio.apply() async def slow_work(label): try: print(f"Starting {label}") await asyncio.sleep(5) # Simulating slow I/O return f"Done {label}" except asyncio.CancelledError: print(f"{label} was cancelled") raise # Re-raising is required async def main(): task = asyncio.create_task(slow_work("task_A")) await asyncio.sleep(1) # Letting the task start task.cancel() try: await task except asyncio.CancelledError: print("Task cancelled successfully") asyncio.run(main())
Always re-raise CancelledError inside a coroutine – swallowing it silently breaks cancellation propagation.
gather() vs wait()
Tak for dine kommentarer!
Spørg AI
Spørg AI
Spørg om hvad som helst eller prøv et af de foreslåede spørgsmål for at starte vores chat