Python asyncio:return vs set_result

Vad*_*rov 2 python python-3.x python-asyncio

您好asyncio专家,

如何正确返回协程的结果?我需要使用return或future.set_result吗?

例如:

@coroutine
def do_something()
    result = yield from some_function()
    return result
Run Code Online (Sandbox Code Playgroud)

要么

@coroutine
def do_something()
    future = asyncio.Future()
    result = yield from some_function()
    future.set_result(result)
Run Code Online (Sandbox Code Playgroud)

dan*_*ano 5

你应该使用return result.你的第二个例子实际上最终将返回None,而不是result.这是一个完整的例子,证明:

from asyncio import coroutine
import asyncio

@asyncio.coroutine
def some_function():
    yield from asyncio.sleep(.5)
    return 5

@coroutine
def do_something():
    result = yield from some_function()
    return result


@coroutine
def do_something_else():
    future = asyncio.Future()
    result = yield from some_function()
    future.set_result(result)

@coroutine
def main():
    print((yield from do_something()))
    print((yield from do_something_else()))

loop = asyncio.get_event_loop()
loop.run_until_complete(main())
Run Code Online (Sandbox Code Playgroud)

输出:

5
None
Run Code Online (Sandbox Code Playgroud)

请注意,如果您实际返回Futurefrom ,它们确实与调用者的角度相同do_something_else:

@coroutine
def do_something_else():
    future = asyncio.Future()
    result = yield from some_function()
    future.set_result(result)
    return future # Now yield from do_something_else() returns 5.
Run Code Online (Sandbox Code Playgroud)

但是当你可以直接回来时,这只是不必要的额外工作result.

在绝大多数情况下,协同程序根本不需要显式创建Future和调用set_result它.这种模式偶尔会有用,但是你最常在单元测试和框架中看到它,而不是在应用程序代码中.

它的一个有趣用途是实现asyncio.sleep:

@coroutine
def sleep(delay, result=None, *, loop=None):
    """Coroutine that completes after a given time (in seconds)."""
    future = futures.Future(loop=loop)
    h = future._loop.call_later(delay, future.set_result, result)
    try:
        return (yield from future)
    finally:
        h.cancel()
Run Code Online (Sandbox Code Playgroud)

在这里Future创建a,set_result计划在调用者想要休眠之后调用该未来的方法,然后yield from在将来调用,这将使函数等待很长时间delay,此时future.set_result(result)调用,并且yield from通话完成.