正确使用 loop.create_future

8 python python-asyncio concurrent.futures

我正在阅读 Python 文档和PyMotW书籍,试图学习 Async/ Await、Futures 和 Tasks。

协程和任务文档

通常不需要在应用程序级代码创建 Future 对象。

未来的文档中,它说明了以下内容:

loop.create_future()

创建一个附加到事件循环的 asyncio.Future 对象。

这是在 asyncio 中创建 Futures 的首选方式。这让第三方事件循环提供 Future 对象的替代实现(具有更好的性能或检测)。

然而,在PyMotW 关于 Future 的章节中,作者创建了一个future这样的对象:

all_done = asyncio.Future()
Run Code Online (Sandbox Code Playgroud)

我猜是因为这本书比 Python 的当前版本稍有落后。为了纠正这个问题,我做了以下事情:

future_Obj = event_loop.create_future()
Run Code Online (Sandbox Code Playgroud)

所以作者的完整代码变成了:

import asyncio


def mark_done(future, result):
    print('setting future result to {!r}'.format(result))
    future.set_result(result)


event_loop = asyncio.get_event_loop()

try:

    future_Obj = event_loop.create_future()
    print('scheduling mark_done')
    event_loop.call_soon(mark_done, future_Obj, 'the result')

    print('entering event loop')
    result = event_loop.run_until_complete(future_Obj)
    print('returned result: {!r}'.format(result))
finally:
    print('closing event loop')
    event_loop.close()

print('future result: {!r}'.format(future_Obj.result()))
Run Code Online (Sandbox Code Playgroud)

题:

future_Obj = event_loop.create_future()上面的示例中,创建一个正确的方法future根据文档对象?

use*_*342 8

future_Obj = event_loop.create_future()在上面的示例中,根据文档创建未来对象的正确方法是吗?

是的,在所示的代码中,这正是执行此操作的方法。

需要注意的一件事是,未来与事件循环相关联,因此在顶层创建未来会创建与asyncio.get_event_loop()最初返回的循环相关联的未来。一旦切换到asyncio.run,您将收到错误,因为每次调用asyncio.run创建一个新的事件循环。

为了避免这个问题,顶级 future 可以从协程开始None并在协程内创建,并global根据需要使用。由于您显式传递未来(这是一个值得遵循的好习惯),因此您根本不需要全局变量:

def mark_done(future, result):
    print('setting future result to {!r}'.format(result))
    future.set_result(result)

async def main():
    loop = asyncio.get_event_loop()
    future = loop.create_future()
    print('scheduling mark_done')
    loop.call_soon(mark_done, future, 'the result')
    print('suspending the coroutine')
    result = await future
    print('awaited result: {!r}'.format(result))
    print('future result: {!r}'.format(future.result()))
    return result

if __name__ == '__main__':
    print('entering the event loop')
    result = asyncio.run(main())
    print('returned result: {!r}'.format(result))
Run Code Online (Sandbox Code Playgroud)

请注意,使用 时asyncio.run,您永远不需要显式关闭循环,这是自动完成的。如果您使用的是 Python 3.6 或更早版本,则可以替换asyncio.run(main())asyncio.get_event_loop().run_until_complete(main()).