Python 异步任务取消

Sus*_*ant 10 python asynchronous python-3.x python-asyncio

我正在阅读任务取消的异步文档,我遇到了这个-

要取消正在运行的任务,请使用 cancel() 方法。调用它会导致任务将 CancelledError 异常抛出到包装的协程中。如果协程在取消期间等待 Future 对象,则 Future 对象将被取消。

cancelled() 可用于检查任务是否被取消。如果包装的协程没有抑制 CancelledError 异常并且实际上被取消,则该方法返回 True 。

我在这里有几个问题 -

  • 包装协程是调用取消的协程吗?让我们在这里举个例子——

    async def wrapped_coroutine():
        for task in asyncio.Task.all_tasks():
            task.cancel()
    
    Run Code Online (Sandbox Code Playgroud)

    那么wrapped_coroutine()封装的协程是否会抛出异常呢?

  • 什么时候会抛出这个异常?在哪里?

  • 这里抑制异常是什么意思?是不是这个意思——

    async def wrapped_coroutine():
        for task in asyncio.Task.all_tasks():
            task.cancel()
            try:
                await task
            except asyncio.CancelledError:
                print("Task cancelled")
    
    Run Code Online (Sandbox Code Playgroud)

    如果没有,请提供有关如何抑制此异常的示例。

还有一个不相关的(它与取消任务有关),当我取消这些任务时如何从这些任务中检索异常,所以我看不到这个 -

Task exception was never retrieved future:
Run Code Online (Sandbox Code Playgroud)

是之前task.cancel()还是try之前await task(在上面的例子中)?

Gri*_*mar 7

查看文档https://docs.python.org/3/library/asyncio-task.html#asyncio.Task.cancel 中给出的示例中的代码:

async def cancel_me():
    print('cancel_me(): before sleep')

    try:
        # Wait for 1 hour
        await asyncio.sleep(3600)
    except asyncio.CancelledError:
        print('cancel_me(): cancel sleep')
        raise
    finally:
        print('cancel_me(): after sleep')

async def main():
    # Create a "cancel_me" Task
    task = asyncio.create_task(cancel_me())

    # Wait for 1 second
    await asyncio.sleep(1)

    task.cancel()
    try:
        await task
    except asyncio.CancelledError:
        print("main(): cancel_me is cancelled now")

asyncio.run(main())
Run Code Online (Sandbox Code Playgroud)

回答您的问题:

  • “包装的协程是调用取消的协程吗?”
    不,这里包裹的协程是cancel_me(); .cancel()被称为main()
  • “什么时候会抛出这个异常?在哪里?” 调用
    后抛出此异常task.cancel()。它在协程中抛出,在示例中被捕获,然后重新引发以在等待程序中抛出并捕获。
  • “这里抑制异常是什么意思?”
    如果cancel_me()在捕获异常后不会重新引发异常。正如文档cancelled()所述:“当使用 cancel() 请求取消并且包装的协程将 CancelledError 异常传播到其中时,任务被取消。” https://docs.python.org/3/library/asyncio-task.html#asyncio.Task.cancelled