如何防止python3.11 TaskGroup取消所有任务

Ant*_* M. 7 python asynchronous python-asyncio python-3.11

我刚刚发现了 Python 3.11 的新功能,如 ExceptionGroup 和 TaskGroup,我对以下 TaskGroup 行为感到困惑:如果组内的一个或多个任务失败,则所有其他正常任务都将被取消,我没有机会更改该行为 示例:

async def f_error():
    raise ValueError()

async def f_normal(arg):
    print('starting', arg)
    await asyncio.sleep(1)
    print('ending', arg)


async with asyncio.TaskGroup() as tg:
    tg.create_task(f_normal(1))
    tg.create_task(f_normal(2))
    tg.create_task(f_error())

# starting 1
# starting 2
#----------
#< traceback of the error here >
Run Code Online (Sandbox Code Playgroud)

在上面的例子中,我无法打印“ending 1”和“ending 2”。asyncio.gather(return_exceptions=True)同时,在发生错误时提供类似选项不取消剩余任务的选项将非常有用。

你可以说“如果你不想要这种取消行为,就不要使用TaskGroup”,但答案是我想使用新的异常组功能,并且它严格绑定到TaskGroup

所以问题是:

  1. 我可以以某种方式在 asyncio 中使用异常组,而无需在 TaskGroup 中使用这种全有或全无的取消策略吗?
  2. 如果对于前面的答案是“否”:为什么 python 开发人员消除了在 TaskGroup API 中禁用取消的可能性?

Pau*_*ius 3

BaseExceptionGroups 在 3.11 版本中成为标准 Python 的一部分。它们不以任何方式绑定到 asyncio TaskGroup。文档位于: https: //docs.python.org/3/library/exceptions.html ?highlight=exceptiongroup#ExceptionGroup 。

关于您的问题 2,在 TaskGroup 上下文中,您始终可以选择使用asyncio.create_task或创建任务loop.create_task。此类任务不会成为 TaskGroup 的一部分,并且不会在 TaskGroup 关闭时被取消。这些任务之一中的异常不会导致组关闭,前提是异常不会传播到组的__aexit__方法中。

您还可以选择处理任务中的所有错误。不传播异常的任务不会取消任务组。

当组退出时强制取消任务有一个很好的理由:组的目的是充当独立的任务集合。允许未取消的任务在组退出后继续执行是矛盾的,可能会导致任务从上下文中泄漏。