Getting values from functions that run as asyncio tasks Getting values from functions that run as asyncio tasks python-3.x python-3.x

Getting values from functions that run as asyncio tasks


The coroutines work as is. Just use the returned value from loop.run_until_complete() and call asyncio.gather() to collect multiple results:

#!/usr/bin/env python3import asyncio@asyncio.coroutinedef func_normal():    print('A')    yield from asyncio.sleep(5)    print('B')    return 'saad'@asyncio.coroutinedef func_infinite():    for i in range(10):        print("--%d" % i)    return 'saad2'loop = asyncio.get_event_loop()tasks = func_normal(), func_infinite()a, b = loop.run_until_complete(asyncio.gather(*tasks))print("func_normal()={a}, func_infinite()={b}".format(**vars()))loop.close()

Output

--0--1--2--3--4--5--6--7--8--9ABfunc_normal()=saad, func_infinite()=saad2


loop.run_until_complete returns the value returned by the function you pass into it. So, it will return the output of asyncio.wait:

import asyncio@asyncio.coroutinedef func_normal():    print("A")    yield from asyncio.sleep(5)    print("B")    return 'saad'@asyncio.coroutinedef func_infinite():    i = 0    while i<10:        print("--"+str(i))        i = i+1    return('saad2')loop = asyncio.get_event_loop()tasks = [    asyncio.async(func_normal()),    asyncio.async(func_infinite())]done, _ = loop.run_until_complete(asyncio.wait(tasks))for fut in done:    print("return value is {}".format(fut.result()))loop.close()

Output:

A--0--1--2--3--4--5--6--7--8--9Breturn value is saad2return value is saad

You can also access the results directly from the tasks array:

print(tasks[0].result())print(tasks[1].result())


If you want to use any value returned by coroutine as soon as coroutine ends you can pass future object into the coro and update this future by computed value. As soon as future is updated it passes its future.result() to the callback function which is bound with given future. See code below:

import asyncioasync def func_normal(future):    print("A")    await asyncio.sleep(5)    print("B")    # return 'saad'    future.set_result('saad')async def func_infinite(future):    i = 0    while i<10:        print("--"+str(i))        i = i+1    # return('saad2')    future.set_result('saad2')def got_result(future):    print(future.result())loop = asyncio.get_event_loop()future1 = asyncio.Future()future2 = asyncio.Future()future1.add_done_callback(got_result)future2.add_done_callback(got_result)# Coros are automatically wrapped in Tasks by asyncio.wait() coros = [    func_normal(future1),    func_infinite(future2)]loop.run_until_complete(asyncio.wait(coros))loop.close()

The callback function is called with a single argument - the future object which it is bound with. If you need to pass more arguments into the callback use partial from functools package:

future1.add_done_callback(functools.partial(print, "future:", argin))

will call

print("future:", argin)