asyncio
Use the async/await syntax to declare coroutines, then use asyncio.run() to schedule it.
import asyncio
async def main():
await asyncio.sleep(1)
print('done')
asyncio.run(main())
Wait for multiple tasks to complete
Use asyncio.gather
import asyncio
async def task(id):
await asyncio.sleep(1)
print(id)
return id
async def main():
tasks = [task(i) for i in range(5)]
results = await asyncio.gather(*tasks)
print(results)
asyncio.run(main())
Output:
0
1
2
3
4
[0, 1, 2, 3, 4]
TaskGroup
TaskGroup works like WaitGroup or Barrier in other languages, but you don't have to explicitly wait for it.
import asyncio
import random
async def task(id):
await asyncio.sleep(random.random())
print(id)
return id
async def main():
async with asyncio.TaskGroup() as g:
task1 = g.create_task(task(1))
task2 = g.create_task(task(2))
print(f"done: {task1.result()}, {task2.result()}")
asyncio.run(main())
Handling exceptions
asyncio.gather works much like Promise.all, if an exception is
raised, it immediately propagated to the task that awaits on
gather(). And other tasks will continue to run.
asyncio.gather also accept keyword argument return_exceptions, when set to True, it works more like Promise.allSettled.
import asyncio
async def task(id):
await asyncio.sleep(1)
print(id)
return id
async def main():
tasks = [task(i) for i in range(5)]
results = await asyncio.gather(*tasks, return_exceptions=True)
print(results)
asyncio.run(main())
Output:
[ZeroDivisionError('division by zero'), 1.0, 0.5, 0.3333333333333333, 0.25]
Wait for the first task
asyncio.wait gives you more control than asyncio.gather:
import asyncio
import random
async def task(id):
await asyncio.sleep(random.random())
print(id)
return id
async def main():
# must be a list of Tasks, not coroutines
tasks = [asyncio.create_task(task(i)) for i in range(5)]
done, pending = await asyncio.wait(tasks, return_when=asyncio.FIRST_COMPLETED)
print("done", [x.result() for x in done])
print("pending tasks:", len(pending))
for x in pending:
x.cancel()
asyncio.run(main())
Output:
2
done [2]
pending tasks: 4
Timeout
When timed out, the task is also canceled.
import asyncio
import random
async def task():
await asyncio.sleep(random.random())
print("done")
async def main():
try:
async with asyncio.timeout(0.5):
await task()
except TimeoutError:
print("Timed out")
asyncio.run(main())