Можно ли отменить таск, который только что запустили
Что проверяют
Понимаете ли вы, что cancel() в asyncio это просьба, а не мгновенная остановка, и где отмена вообще невозможна. Следом спрашивают, что делать с потоком и почему except Exception не ловит отмену.
Как отвечать
Для asyncio.Task да. asyncio.create_task() только ставит корутину в очередь цикла событий, выполнение начнётся на ближайшей итерации. Если вызвать task.cancel() до этого, корутина не выполнит ни строчки: CancelledError бросается при первом входе, и try внутри неё не успевает сработать. Если задача уже работает, исключение прилетит в точке ближайшего await.
Что важно проговорить:
cancel()возвращаетFalse, если задача уже завершена, иTrue, если запрос принят;CancelledErrorнаследуетBaseExceptionс Python 3.8, поэтомуexcept Exceptionего не глотает. После очистки ресурсов исключение нужно пробросить дальше;- код без
awaitотменить нельзя: цикл чистых вычислений дойдёт до конца; - современные средства:
asyncio.timeout()иTaskGroupс Python 3.11 сами отменяют задачи по таймауту или при падении соседа,asyncio.shield()защищает операцию от внешней отмены.
Потоки устроены иначе. Убить threading.Thread снаружи нельзя, его останавливают кооперативно через threading.Event, который поток сам проверяет. concurrent.futures.Future.cancel() сработает, только пока задача ждёт в очереди, для запущенной вернёт False. При остановке пула поможет shutdown(cancel_futures=True).
Если речь о Celery, revoke() отменит задачу, которую ещё не взял воркер. Запущенную останавливает только terminate=True, то есть сигнал процессу без гарантии корректного завершения.
Где спотыкаются
Пишут голый except: или except BaseException вокруг await и глотают отмену. Задача продолжает работать, а TaskGroup и таймауты ломаются.
Вызывают cancel() и сразу считают задачу остановленной: трогают общее состояние или закрывают соединение, пока в задаче ещё идёт finally. Нужен await task с обработкой CancelledError.
Ищут способ убить поток и находят ctypes с принудительным исключением. Это оставляет захваченные блокировки и повреждённое состояние.