Метод cancel() модуля asyncio в Python — отмена задачи

D этом руководстве вы узнаете, как отменить длительную асинхронную операцию в Python, выполнение которой может занять целую вечность, с помощью метода cancel() объекта asyncio.Task.

В следующем примере используется оператор await для ожидания завершения задачи:

task = asyncio.create_task(coroutine())

result = await task

Однако, если coroutine() будет длиться вечно, вы застрянете в ожидании завершения оператора await, не получив никакого результата. Кроме того, у вас нет возможности остановить это, когда вы пожелаете.

Чтобы решить эту проблему, вы можете отменить задачу, используя метод cancel() объекта Task. Если вы отмените задачу, она вызовет исключение CancelledError, когда вы ее ожидаете. Например:

import asyncio
from asyncio import CancelledError


async def call_api(message, result=1000, delay=3):
    print(message)
    await asyncio.sleep(delay)
    return result


async def main():
    task = asyncio.create_task(
        call_api('Calling API...', result=2000, delay=5)
    )

    if not task.done():
        print('Cancelling the task...')
        task.cancel()

    try:
        await task
    except CancelledError:
        print('Task has been cancelled.')


asyncio.run(main())

Выход:

Cancelling the task...
Task has been cancelled

Как это работает.

  • Сначала сопрограмма call_api() печатает сообщение, задерживается на 3 секунды и возвращает результат.
  • Во-вторых, создайте новую задачу с помощью функции create_task() и передайте сопрограмму call_api(). Выполнение задачи займет 5 секунд:
task = asyncio.create_task(
    call_api('Calling API...', result=2000, delay=5)
)
  • В-третьих, проверьте, не выполнена ли задача, вызвав метод Done(), и отмените задачу, используя метод cancel():
if not task.done():
    print('Cancelling the task...')
    task.cancel()
  • Наконец, дождитесь завершения задачи, используя ключевое слово await. Поскольку задача была отменена, возникает исключение CancelledError:
try:
    await task
except CancelledError:
    print('Task has been cancelled.')

Если вы хотите проверять, выполнена ли задача, и отменить ее, если прошло определенное время, вы можете использовать цикл while:

import asyncio
from asyncio import CancelledError


async def call_api(message, result=1000, delay=3):
    print(message)
    await asyncio.sleep(delay)
    return result


async def main():
    task = asyncio.create_task(
        call_api('Calling API...', result=2000, delay=5)
    )

    time_elapsed = 0
    while not task.done():
        time_elapsed += 1
        await asyncio.sleep(1)
        print('Task has not completed, checking again in a second')
        if time_elapsed == 3:
            print('Cancelling the task...')
            task.cancel()
            break

    try:
        await task
    except CancelledError:
        print('Task has been cancelled.')


asyncio.run(main())

В этом примере цикл while проверяет, выполнена ли задача каждую секунду, и отменяет задачу, как только прошедшее время достигнет 3 секунд.

Похожие посты
Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *