Поэтому, в отличие от Future.cancel(), Task.cancel() не гарантирует, что Задача будет отменена, хотя полное подавление отмены не является распространенным явлением и активно не рекомендуется. Если сопрограмма все же решит подавить отмену, ей необходимо вызвать Task.uncancel() в дополнение к перехвату исключения.
Однако ни один из методов обнаружения отмены не является ожидаемым: cancelling сообщает вам, выполняется ли отмена, и cancelled сообщает вам, выполнена ли отмена. Итак, очевидный способ дождаться отмены:
Код: Выделить всё
foo_task.cancel()
try:
await foo_task
except asyncio.CancelledError:
pass
Компоненты asyncio, обеспечивающие структурированный параллелизм, такие как asyncio.TaskGroup и asyncio.timeout(), реализованы с использованием внутренней отмены и могут работать неправильно, если сопрограмма проглотит asyncio.CancelledError
Теперь вы может быть интересно, почему вы должны ждать, чтобы заблокировать задачу, пока задача не будет полностью отменена. Проблема в том, что цикл событий asyncio создает только слабые ссылки на задачи, поэтому, если ваш класс завершает работу (например, из-за метода очистки или __aexit__) и вы не ожидаете каждой создаваемой вами задачи, вы можете удалить единственную сильную ссылку, пока задача все еще выполняется, и тогда Python будет кричать на вас:
Код: Выделить всё
ERROR base_events.py:1771: Task was destroyed but it is pending!
Подробнее здесь: https://stackoverflow.com/questions/779 ... yncio-task
Мобильная версия