Limit Async Task Fan-Out With Semaphore
Run many async coroutines while capping concurrency with a semaphore, avoiding the flood of pending tasks that unbounded gathering creates.
Code
import asyncio
from typing import Awaitable, List, TypeVar
T = TypeVar("T")
async def gather_limited(
tasks: List[Awaitable[T]], limit: int
) -> List[T]:
if limit <= 0:
raise ValueError("limit must be positive")
semaphore = asyncio.Semaphore(limit)
async def guarded(task: Awaitable[T]) -> T:
async with semaphore:
return await task
return await asyncio.gather(*(guarded(t) for t in tasks))
async def fetch(i: int) -> str:
await asyncio.sleep(0.01)
return f"item-{i}"
async def main() -> None:
results = await gather_limited([fetch(i) for i in range(20)], 5)
print(len(results))Report a problem with this exampleOpens a pre-filled issue on GitHub.