Getting values from functions that run as asyncio tasks

前端 未结 3 1735
-上瘾入骨i
-上瘾入骨i 2021-02-06 20:28

I was trying the following code:

import asyncio

@asyncio.coroutine
def func_normal():
        print(\"A\")
        yield from asyncio.sleep(5)
        print(\"B         


        
相关标签:
3条回答
  • 2021-02-06 21:01

    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 python3
    import asyncio
    
    @asyncio.coroutine
    def func_normal():
        print('A')
        yield from asyncio.sleep(5)
        print('B')
        return 'saad'
    
    @asyncio.coroutine
    def 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
    --9
    A
    B
    func_normal()=saad, func_infinite()=saad2
    
    0 讨论(0)
  • 2021-02-06 21:14

    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.coroutine
    def func_normal():
        print("A")
        yield from asyncio.sleep(5)
        print("B")
        return 'saad'
    
    @asyncio.coroutine
    def 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
    --9
    B
    return value is saad2
    return value is saad
    

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

    print(tasks[0].result())
    print(tasks[1].result())
    
    0 讨论(0)
  • 2021-02-06 21:18

    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 asyncio
    
    
    async 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)
    
    0 讨论(0)
提交回复
热议问题