asyncio.wait() and Task Control
Glissez pour afficher le menu
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()
Merci pour vos commentaires !
Demandez à l'IA
Demandez à l'IA
Posez n'importe quelle question ou essayez l'une des questions suggérées pour commencer notre discussion