正确使用loop.create_future

时间:2019-01-20 02:16:46

标签: python python-asyncio concurrent.futures

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

Coroutines and Tasks documentation

  

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

future documentation中声明以下内容:

  

loop.create_future()

     

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

     

这是在asyncio中创建Futures的首选方法。这样,第三方事件循环就可以提供   未来的对象(具有更好的性能或仪器)。

但是,作者在PyMotW chapter on Future中创建了一个future对象,如下所示:

all_done = asyncio.Future()

我认为是因为本书略落后于当前版本的Python。为了解决这个问题,我做了以下事情:

future_Obj = event_loop.create_future()

因此,作者的完整代码变为:

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

问题:

以上示例中的future_Obj = event_loop.create_future()是根据文档创建future对象的正确方法吗?

1 个答案:

答案 0 :(得分:0)

  

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

是的,在所示的代码中,这正是这样做的方法。

要注意的一件事是,future与事件循环相关联,因此在顶级创建future与asyncio.get_event_loop()最初返回的循环相关联。切换到asyncio.run后,您会收到一条错误消息,因为每次调用asyncio.run都会创建一个新的事件循环。

为避免该问题,高层的未来可以从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))

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