Python Asyncio任务取消

时间:2019-05-09 05:28:39

标签: python python-3.x asynchronous python-asyncio

我正在阅读asyncio文档以了解任务取消,并且遇到this-

  

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

     

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

我在这里有几个问题-

  • 包装的协程是否称为取消的协程?让我们在这里举个例子-

    async def wrapped_coroutine():
        for task in asyncio.Task.all_tasks():
            task.cancel()
    

    wrapped_coroutine()是包装好的协程,任务将在该协程中引发异常?

  • 何时将引发此异常?在哪里?

  • 抑制异常在这里意味着什么?这是否意味着-

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

    如果没有,请提供一个示例来说明如何抑制此异常。

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

Task exception was never retrieved future:

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

1 个答案:

答案 0 :(得分:1)

看文档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())

回答您的问题:

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