APIs and Async · Async Python · lesson 7 of 12
Running things concurrently
about 16 minutes · free · runs in your browser
await in a loop is still serial
This is the mistake worth understanding, because the code looks concurrent and is not:
results = []
for city in cities:
results.append(await fetch(city)) # each one waits for the last
Three requests at 100ms take 300ms. asyncio.gather starts them all and waits for the
set:
results = await asyncio.gather(*(fetch(c) for c in cities))
Now they overlap, and three requests take about 100ms. gather returns the results
in the order you passed them in, not the order they finished — which is what makes it
safe to zip back against the inputs.
If one raises, gather propagates it and abandons the rest. Pass
return_exceptions=True to get the exception as a result instead and carry on.
Your turn: write fetch_all(cities) that fetches every city concurrently and
returns a list of temperatures in the same order.
You start from this, and edit it in the browser:
import asyncio
import fake_httpx as httpx
BASE = "https://api.pylearn.dev"
async def fetch_temp(client, city):
response = await client.get("/weather", params={"city": city})
return response.json()["temp_c"]
async def fetch_all(cities):
# Fetch every city concurrently and return the temperatures in order.
pass