I'm trying to write something as idiomatic as possible to gather results from futures stored in a dict.
Let's imagine I have the following code:
import asyncio
async def sleep(seconds):
print(f'sleeping for {seconds} seconds')
await asyncio.sleep(seconds)
print(f'finished sleeping {seconds} seconds')
async def run():
tasks = {
'4': sleep(4),
'3': sleep(3),
'2': sleep(2),
'1': sleep(1),
}
print(await gather_from_dict(tasks))
if __name__ == '__main__':
asyncio.get_event_loop().run_until_complete(run())
The output I'm expecting is:
sleeping for 2 seconds
sleeping for 1 seconds
sleeping for 4 seconds
sleeping for 3 seconds
finished sleeping 1 seconds
finished sleeping 2 seconds
finished sleeping 3 seconds
finished sleeping 4 seconds
{'4': None, '3': None, '2': None, '1': None}
So far the cleanest solution I've found is:
async def gather_from_dict(tasks:Dict[Hashable, Awaitable],
loop=None, return_exceptions=False) -> Dict:
results = await asyncio.gather(
*tasks.values(),
loop=loop,
return_exceptions=return_exceptions
)
return dict(zip(tasks.keys(), results))
Any ideas on how to do this in a simpler way? Thanks!!!
With Python 3.7, a dictionary is guaranteed to be iterated in the insertion order of keys. If you need to iterate over a dictionary in sorted order of its keys or values, you can pass the dictionary's entries to the sorted() function, which returns a list of tuples.
Dictionary iteration order happens to be in order of insertion in CPython implementation, but it is not a documented guarantee of the language.
Check if Variable is a Dictionary with is Operator We can use the is operator with the result of a type() call with a variable and the dict class. It will output True only if the type() points to the same memory location as the dict class. Otherwise, it will output False .
Dictionaries are used to store data values in key:value pairs. A dictionary is a collection which is ordered*, changeable and do not allow duplicates. As of Python version 3.7, dictionaries are ordered. In Python 3.6 and earlier, dictionaries are unordered.
I redefined your tasks to make it purer as coroutine lists, and prefer to get the results from the run_until_complete methods, codes like the following, and notice that I return something in your sleep codes, in your codes, you actually return None.
import asyncio
async def sleep(seconds):
print('sleeping for {seconds} seconds'.format(seconds=seconds))
await asyncio.sleep(seconds)
print('finished sleeping {seconds} seconds'.format(seconds=seconds))
return {seconds: 'value of {seconds}'.format(seconds=seconds)}
if __name__ == '__main__':
loop = asyncio.get_event_loop()
tasks = [sleep(i) for i in range(1, 5)]
finished, _ = loop.run_until_complete(
asyncio.wait(tasks))
result = {}
for task in finished:
result.update(task.result())
print(result)
loop.close()
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With