Three ways to run multiple coroutines concurrently. Each has its own niche.
asyncio.gather() โ the simplest
import asyncio, httpx
async def fetch(client, url):
r = await client.get(url)
return r.status_code
async def main():
urls = ["https://httpbin.org/get"] * 5
async with httpx.AsyncClient() as client:
# All 5 requests run in parallel
results = await asyncio.gather(*[fetch(client, u) for u in urls])
print(results) # [200, 200, 200, 200, 200]
asyncio.run(main())
gather() returns results in the same order as the input coroutines.
asyncio.create_task() โ when you need control
async def main():
# Task is created and IMMEDIATELY starts running
task1 = asyncio.create_task(fetch(client, url1), name="fetch-1")
task2 = asyncio.create_task(fetch(client, url2), name="fetch-2")
# Can cancel while waiting
await asyncio.sleep(0.1)
task1.cancel() # changed my mind
try:
result = await task2
except asyncio.CancelledError:
pass
asyncio.wait() and as_completed() โ for complex scenarios
async def main():
tasks = {asyncio.create_task(fetch(c, u)) for u in urls}
# Process as they complete โ don't wait for the slowest
async for coro in asyncio.as_completed(tasks):
result = await coro
print(f"Done: {result}")
TaskGroup (Python 3.11+) โ structured concurrency
async def main():
results = []
async with asyncio.TaskGroup() as tg:
for url in urls:
tg.create_task(fetch_and_save(url, results))
# Reach here only when ALL tasks complete
# If one fails โ all others are automatically cancelled
print(f"Collected: {len(results)}")
TaskGroup is the right choice for new code. It guarantees that when one task fails the others won’t hang forever.
๐ฌ Comments (0)
No comments yet
Be the first to share your opinion about this article!