Python 从作为异步任务运行的函数中获取值

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/32456881/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-19 11:36:36  来源:igfitidea点击:

Getting values from functions that run as asyncio tasks

pythonpython-3.xpython-3.4python-asyncio

提问by Saad Aleem

I was trying the following code:

我正在尝试以下代码:

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())]

loop.run_until_complete(asyncio.wait(tasks))
loop.close()

I can't figure out how to get values in variables from these functions. I can't do this:

我不知道如何从这些函数中获取变量中的值。我不能这样做:

asyncio.async(a = func_infinite())

as this would make this a keyword argument. How do I go about accomplishing this?

因为这会使 this 成为关键字参数。我该如何去完成这个?

采纳答案by jfs

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

协程按原样工作。只需使用 fromloop.run_until_complete()callasyncio.gather()的返回值来收集多个结果

#!/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

回答by dano

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

loop.run_until_complete返回您传递给它的函数返回的值。因此,它将返回以下输出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 tasksarray:

您还可以直接从tasks数组访问结果:

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

回答by Petr Javorik

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:

如果您想在协程结束后立即使用协程返回的任何值,您可以将未来对象传递给 coro 并通过计算值更新这个未来。一旦future 被更新,它就会将它的future.result() 传递给与给定future 绑定的回调函数。见下面的代码:

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:

回调函数使用单个参数调用 - 它绑定的未来对象。如果您需要将更多参数传递到回调中,请使用 functools 包中的 partial:

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

will call

将会通知

print("future:", argin)