取消 asyncio.gather()
任务后,我希望 task.cancelled()
返回 True
但它返回 错误
。
问题
- 这是预期的吗?
- 当
Future.cancel()
设置self._state = _CANCELLED
时,重写的_GatheringFuture.cancel()
不会设置self ._state
。 (task.cancelled()
使用task._state
)。这是设计使然吗?
示例
def test_gather_cancellation_cancels_children_but_not_itself():
# loop
loop = new_event_loop()
set_event_loop(loop)
# create tasks and schedule them in gather
task_child = ensure_future(sleep(1.0, result=1))
task_gather = gather(task_child, return_exceptions=False)
# assert nothing cancelled/done
assert task_child.cancelled() is False
assert task_gather.cancelled() is False
assert task_child.done() is False
assert task_gather.done() is False
# cancel and await finishing of children
assert task_gather.cancel() is True
try:
with pytest.raises(CancelledError):
loop.run_until_complete(task_gather)
finally:
set_event_loop(None)
loop.close()
# assert all cancelled
assert task_child.cancelled() is True
# SURPRISING ASSERTION HERE:
# surprisingly this is False because the the internal
# task._state variable is not set in overridden
# _GatheringFuture.cancel()
assert task_gather.cancelled() is False # this is surprising, expected True
# assert all done
assert task_child.done() is True
assert task_gather.done() is True
============================= test session starts =============================
platform win32 -- Python 3.8.3rc1, pytest-5.4.2, py-1.8.1, pluggy-0.13.1 --
collecting ... collected 1 item
tests/gather/test_gather.py::test_gather_cancellation_cancels_children_but_not_itself PASSED [100%]
文档
Python docs提到这一点:
If gather() is cancelled, all submitted awaitables (that have not completed yet) are also cancelled. If any Task or Future from the aws sequence is cancelled, it is treated as if it raised CancelledError – the gather() call is not cancelled in this case. This is to prevent the cancellation of one submitted Task/Future to cause other Tasks/Futures to be cancelled.
但是,在我看来,这仅当从外部取消收集的任务时才适用!当在 gather()
任务(及其子任务)上显式运行 cancel() 时,task.cancelled()
似乎令人惊讶是False
。因此我不确定文档中描述的情况是否适用于此处。
最佳答案
对于任何感兴趣的人:我已在 bugs.python.org 上提交了错误报告。该问题已由 asyncio 核心开发人员审核,通常被视为优先级较低的错误。我还创建了一个 PR 来修复它,等待低优先级审核。
关于python - asyncio.gather() - task.cancelled() 在 task.cancel() 之后为 False,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61942306/