We can't find the internet
Attempting to reconnect
Something went wrong!
Attempting to reconnect
← Concurrency with Threads and asyncio step 22 of 56
Resolve Values, Awaitables and Factories in Order
A settings loader gets a list of sources. Some are plain numbers. Some are
awaitables, such as a coroutine that looks a value up. Some are
factories, functions with no arguments that create the awaitable only
when you call them. Write resolve_all, which turns each source into its
value, one source at a time and in order.
async def double(n: int) -> int:
return n * 2
await resolve_all([1, double(2), lambda: double(3)]) # [1, 4, 6]
What to write
Fill in resolve_all, and keep the rest of the starter as it is. Go through
sources in order, and finish each source before you call or await the next:
- If the source is callable, call it once with no arguments and take the result. Otherwise take the source itself.
- If what you took is an
Awaitablefromcollections.abc, await it once. Otherwise use it as it is. - Append the value to the list you return.
Also follow these rules:
- Check
callablefirst. An object that is both callable and awaitable gets called. - Start no tasks of your own, and don't use
asyncio.gather. The report checks that each factory runs only whenresolve_allreaches it. - If a factory or an await raises, let the exception propagate, and call no later factories.
- Keep the generic signature. Your code must pass
mypy --strictwithoutAny, casts or# type: ignore.
An empty list gives [].
Tasks in the input
Some sources are tasks. As asyncio from Zero showed, asyncio.create_task
hands a coroutine to the event loop to run on its own. The task starts as
soon as your code pauses at an await and lets the loop run. That can happen
before resolve_all reaches it. Await it like any other awaitable. Its result
still goes in its own place in the output, even if it finishes before the
sources ahead of it.
What the driver reports
solve takes three lists of the same length, kinds, values and hops.
Each kind is "value", "coro", "factory" or "task", and the driver
builds that kind of source from the matching value. Each coroutine it builds
logs its value when its body starts, waits hops loop turns with
asyncio.sleep(0), and returns value * 10 + hops. Each factory logs its
value when you call it.
values: the listresolve_allreturned.started: the values whose coroutines started, in the order they started.calls: the factory values, in the order you called them.pending: other tasks still unfinished at the end. It must be0.
With kinds=["value", "coro", "factory", "task"], values=[1, 2, 3, 4] and
hops=[0, 3, 1, 2], the report has values=[1, 23, 31, 42],
started=[2, 4, 3] and calls=[3]. The task for 4 starts while you await
the coroutine for 2.
Your code, saved here
Sign in to access your accepted solutions and saved draft history. You can keep reading the lesson without an account.
Sign in to your accountStuck?
Python reference solution
Sign in to track your attempts toward unlocking the reference solution.