python runtime_error ai_generated true

asyncio.exceptions.CancelledError:任务被销毁但仍在等待中!

asyncio.exceptions.CancelledError: Task was destroyed but it is pending!

ID: python/asyncio-gather-cancelled-error

其他格式: JSON · Markdown 中文 · English
80%修复率
85%置信度
0证据数
2024-03-15首次发现

版本兼容性

版本状态引入弃用备注
3.8 active
3.9 active
3.10 active

根因分析

使用 asyncio.gather() 且 return_exceptions=False 时,如果某个任务因超时等原因抛出 CancelledError,gather 被取消,其他任务未被正确等待,导致待处理任务销毁警告。

English

When using asyncio.gather() with return_exceptions=False, if one task raises CancelledError (e.g., due to timeout), the gather is cancelled and other tasks are not properly awaited, leading to pending task destruction warnings.

generic

解决方案

  1. 90% 成功率
    results = await asyncio.gather(*tasks, return_exceptions=True)
    for r in results:
        if isinstance(r, asyncio.CancelledError):
            # handle cancellation gracefully
  2. 85% 成功率
    done, pending = await asyncio.wait(tasks, return_when=asyncio.FIRST_EXCEPTION)
    for task in pending:
        task.cancel()
    await asyncio.gather(*pending, return_exceptions=True)

无效尝试

常见但无效的做法:

  1. 60% 失败

    CancelledError is not always raised synchronously; it can be raised during await, and ignoring it may leave tasks in inconsistent states.

  2. 70% 失败

    Shield only protects against cancellation of the outer task, not the inner tasks; it doesn't solve the root issue of pending tasks.