正确使用 loop.create_future
Correctly using loop.create_future
我正在阅读 Python 文档和 PyMotW 书籍,试图学习 Async/Await、Futures 和 Tasks。
Coroutines and Tasks documentation:
Normally there is no need to create Future objects at the application
level code.
来自 future documentation 的内容如下:
loop.create_future()
Create an asyncio.Future object attached to the event loop.
This is the preferred way to create Futures in asyncio. This lets third-party event loops provide alternative implementations of the
Future object (with better performance or instrumentation).
然而,在 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
对象的正确方法吗?
Is future_Obj = event_loop.create_future()
in the sample above, the correct way to create a future object according to the documentation?
是的,在如图所示的代码中,正是这样做的方式。
需要注意的一件事是未来与事件循环相关联,因此在顶层创建未来会创建与最初 asyncio.get_event_loop()
returns 循环相关的未来。一旦你切换到 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))
请注意,使用 asyncio.run
时,您无需明确关闭循环,它会自动完成。如果您使用的是 Python 3.6 或更早版本,则可以将 asyncio.run(main())
替换为 asyncio.get_event_loop().run_until_complete(main())
。
我正在阅读 Python 文档和 PyMotW 书籍,试图学习 Async/Await、Futures 和 Tasks。
Coroutines and Tasks documentation:
Normally there is no need to create Future objects at the application level code.
来自 future documentation 的内容如下:
loop.create_future()
Create an asyncio.Future object attached to the event loop.
This is the preferred way to create Futures in asyncio. This lets third-party event loops provide alternative implementations of the Future object (with better performance or instrumentation).
然而,在 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
对象的正确方法吗?
Is
future_Obj = event_loop.create_future()
in the sample above, the correct way to create a future object according to the documentation?
是的,在如图所示的代码中,正是这样做的方式。
需要注意的一件事是未来与事件循环相关联,因此在顶层创建未来会创建与最初 asyncio.get_event_loop()
returns 循环相关的未来。一旦你切换到 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))
请注意,使用 asyncio.run
时,您无需明确关闭循环,它会自动完成。如果您使用的是 Python 3.6 或更早版本,则可以将 asyncio.run(main())
替换为 asyncio.get_event_loop().run_until_complete(main())
。