python - asyncio.gather() - task.cancelled() 在 task.cancel() 之后为 False

标签 python python-3.x async-await python-asyncio

取消 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/

相关文章:

python - 这个语法叫什么? (int)(value) 与 int(value) 相同

python - 按列表顺序替换值

javascript - d3.queue.await 函数未被调用

python - 从 Python 脚本使用 POST 发送文件

python高级搜索库

python - Django 保存随机行为

python - 如何在 Avro 模式中嵌套记录?

python - 检查列表中至少有一个关键字实例

c# - 使用 HttpClient 异步方法返回格式错误的字符串

c# - 具有异步等待和 GetType().IsValueType 的可移植类库