等待 asyncio.Future 引发 concurrent.futures._base.CancelledError 而不是等待 value/exception 被设置
Awaiting an asyncio.Future raises concurrent.futures._base.CancelledError instead of waiting for a value/exception to be set
当我运行以下python代码时:
import asyncio
import logging
logging.basicConfig(level=logging.DEBUG)
async def read_future(fut):
print(await fut)
async def write_future(fut):
fut.set_result('My Value')
async def main():
loop = asyncio.get_running_loop()
fut = loop.create_future()
asyncio.gather(read_future(fut), write_future(fut))
asyncio.run(main(), debug=True)
而不是 read_future
等待 fut
的结果被设置,程序崩溃并出现以下错误:
DEBUG:asyncio:Using selector: KqueueSelector
ERROR:asyncio:_GatheringFuture exception was never retrieved
future: <_GatheringFuture finished exception=CancelledError() created at /Users/<user>/.pyenv/versions/3.7.4/lib/python3.7/asyncio/tasks.py:642>
source_traceback: Object created at (most recent call last):
File "<stdin>", line 1, in <module>
File "/Users/<user>/.pyenv/versions/3.7.4/lib/python3.7/asyncio/runners.py", line 43, in run
return loop.run_until_complete(main)
File "/Users/<user>/.pyenv/versions/3.7.4/lib/python3.7/asyncio/base_events.py", line 566, in run_until_complete
self.run_forever()
File "/Users/<user>/.pyenv/versions/3.7.4/lib/python3.7/asyncio/base_events.py", line 534, in run_forever
self._run_once()
File "/Users/<user>/.pyenv/versions/3.7.4/lib/python3.7/asyncio/base_events.py", line 1763, in _run_once
handle._run()
File "/Users/<user>/.pyenv/versions/3.7.4/lib/python3.7/asyncio/events.py", line 88, in _run
self._context.run(self._callback, *self._args)
File "<stdin>", line 4, in main
File "/Users/<user>/.pyenv/versions/3.7.4/lib/python3.7/asyncio/tasks.py", line 766, in gather
outer = _GatheringFuture(children, loop=loop)
File "/Users/<user>/.pyenv/versions/3.7.4/lib/python3.7/asyncio/tasks.py", line 642, in __init__
super().__init__(loop=loop)
concurrent.futures._base.CancelledError
DEBUG:asyncio:Close <_UnixSelectorEventLoop running=False closed=False debug=True>
我在这段代码中做错了什么?我希望能够等待 Future fut
并在 Future 设置 value/exception 后继续。
来自https://docs.python.org/3/library/asyncio-future.html#asyncio.Future.result:
result()
Return the result of the Future.
If the Future is done and has a result set by the set_result()
method, the result value is returned.
If the Future is done and has an exception set by the set_exception()
method, this method raises the exception.
If the Future has been cancelled, this method raises a CancelledError
exception.
If the Future’s result isn’t yet available, this method raises a InvalidStateError
exception.
(加粗。)
我不确定为什么 Future
被取消了,但这似乎是问题的原因。
您的问题是 asyncio.gather
is itself async(returns 等待);如果不 await
处理它,您就不会将控制权交还给事件循环,也不会存储可等待对象,因此它会立即被清理,隐式取消它,并且通过扩展,它控制的所有可等待对象。
要修复,只需确保 await
gather
的结果:
await asyncio.gather(read_future(fut), write_future(fut))
当我运行以下python代码时:
import asyncio
import logging
logging.basicConfig(level=logging.DEBUG)
async def read_future(fut):
print(await fut)
async def write_future(fut):
fut.set_result('My Value')
async def main():
loop = asyncio.get_running_loop()
fut = loop.create_future()
asyncio.gather(read_future(fut), write_future(fut))
asyncio.run(main(), debug=True)
而不是 read_future
等待 fut
的结果被设置,程序崩溃并出现以下错误:
DEBUG:asyncio:Using selector: KqueueSelector
ERROR:asyncio:_GatheringFuture exception was never retrieved
future: <_GatheringFuture finished exception=CancelledError() created at /Users/<user>/.pyenv/versions/3.7.4/lib/python3.7/asyncio/tasks.py:642>
source_traceback: Object created at (most recent call last):
File "<stdin>", line 1, in <module>
File "/Users/<user>/.pyenv/versions/3.7.4/lib/python3.7/asyncio/runners.py", line 43, in run
return loop.run_until_complete(main)
File "/Users/<user>/.pyenv/versions/3.7.4/lib/python3.7/asyncio/base_events.py", line 566, in run_until_complete
self.run_forever()
File "/Users/<user>/.pyenv/versions/3.7.4/lib/python3.7/asyncio/base_events.py", line 534, in run_forever
self._run_once()
File "/Users/<user>/.pyenv/versions/3.7.4/lib/python3.7/asyncio/base_events.py", line 1763, in _run_once
handle._run()
File "/Users/<user>/.pyenv/versions/3.7.4/lib/python3.7/asyncio/events.py", line 88, in _run
self._context.run(self._callback, *self._args)
File "<stdin>", line 4, in main
File "/Users/<user>/.pyenv/versions/3.7.4/lib/python3.7/asyncio/tasks.py", line 766, in gather
outer = _GatheringFuture(children, loop=loop)
File "/Users/<user>/.pyenv/versions/3.7.4/lib/python3.7/asyncio/tasks.py", line 642, in __init__
super().__init__(loop=loop)
concurrent.futures._base.CancelledError
DEBUG:asyncio:Close <_UnixSelectorEventLoop running=False closed=False debug=True>
我在这段代码中做错了什么?我希望能够等待 Future fut
并在 Future 设置 value/exception 后继续。
来自https://docs.python.org/3/library/asyncio-future.html#asyncio.Future.result:
result()
Return the result of the Future.
If the Future is done and has a result set by the
set_result()
method, the result value is returned.If the Future is done and has an exception set by the
set_exception()
method, this method raises the exception.If the Future has been cancelled, this method raises a
CancelledError
exception.If the Future’s result isn’t yet available, this method raises a
InvalidStateError
exception.
(加粗。)
我不确定为什么 Future
被取消了,但这似乎是问题的原因。
您的问题是 asyncio.gather
is itself async(returns 等待);如果不 await
处理它,您就不会将控制权交还给事件循环,也不会存储可等待对象,因此它会立即被清理,隐式取消它,并且通过扩展,它控制的所有可等待对象。
要修复,只需确保 await
gather
的结果:
await asyncio.gather(read_future(fut), write_future(fut))