Отмена задачи Python Asyncio - PullRequest
1 голос
/ 09 мая 2019

Я читал документацию asyncio для отмены задачи, и я наткнулся на this -

Чтобы отменить запущенную задачу, используйте метод cancel (). Вызов этого приведет к тому, что Задача сгенерирует исключение CancelledError в завернутую сопрограмму. Если сопрограмма ожидает объекта Future во время отмены, объект Future будет отменен.

cancelled () можно использовать для проверки отмены задания. Метод возвращает True, если завернутая сопрограмма не подавила исключение CancelledError и была фактически отменена.

У меня есть несколько вопросов здесь -

  • Является ли завернутая сопрограмма сопрограммой, в которой вызывается отмена? Давайте рассмотрим пример здесь -

    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 Ответ

1 голос
/ 09 мая 2019

Глядя на код в примере, приведенном в документации 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
...