Как правильно дождаться отмены задачи asyncio?Python

Программы на Python
Ответить
Anonymous
 Как правильно дождаться отмены задачи asyncio?

Сообщение Anonymous »

Документация по отмене звучит так, как будто вы обычно должны распространять исключения CancelledError:

Поэтому, в отличие от Future.cancel(), Task.cancel() не гарантирует, что Задача будет отменена, хотя полное подавление отмены не является распространенным явлением и активно не рекомендуется. Если сопрограмма все же решит подавить отмену, ей необходимо вызвать Task.uncancel() в дополнение к перехвату исключения.

Однако ни один из методов обнаружения отмены не является ожидаемым: cancelling сообщает вам, выполняется ли отмена, и cancelled сообщает вам, выполнена ли отмена. Итак, очевидный способ дождаться отмены:

Код: Выделить всё

foo_task.cancel()
try:
await foo_task
except asyncio.CancelledError:
pass
В Интернете есть множество примеров этого, даже на SO. Но документация предупреждает, что асинхронное оборудование будет «неправильно себя вести», если вы сделаете это:

Компоненты asyncio, обеспечивающие структурированный параллелизм, такие как asyncio.TaskGroup и asyncio.timeout(), реализованы с использованием внутренней отмены и могут работать неправильно, если сопрограмма проглотит asyncio.CancelledError

Теперь вы может быть интересно, почему вы должны ждать, чтобы заблокировать задачу, пока задача не будет полностью отменена. Проблема в том, что цикл событий asyncio создает только слабые ссылки на задачи, поэтому, если ваш класс завершает работу (например, из-за метода очистки или __aexit__) и вы не ожидаете каждой создаваемой вами задачи, вы можете удалить единственную сильную ссылку, пока задача все еще выполняется, и тогда Python будет кричать на вас:

Код: Выделить всё

ERROR base_events.py:1771: Task was destroyed but it is pending!
Таким образом, похоже, чтобы избежать ошибки, меня специально заставляют делать то, что я не должен делать :P Единственной альтернативой кажется странный непитонический хакерский подход, такой как помещение каждой задачи, которую я делаю, в глобальный набор и ожидание их всех в конце выполнения.>

Подробнее здесь: https://stackoverflow.com/questions/779 ... yncio-task
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «Python»