TL; DR Не используйте set_exception_handler
для обработки исключений в задачах. Вместо этого добавьте реквизит try: ... except: ...
в саму сопрограмму.
Проблема заключается в попытке использовать set_exception_handler
для обработки исключений. Эта функция является последней попыткой обнаружить исключение, которое прошло до события l oop, скорее всего, в результате ошибки в программе. Если обратный вызов добавлен с помощью loop.call_soon
или loop.call_at
et c. вызывает исключение (и не улавливает его), обработчик, установленный set_exception_handler
, будет последовательно вызываться.
С задачей все более тонко: задача доводит сопрограмму до завершения и, когда она выполняется, сохраняет свой результат , делая его доступным для всех, кто ожидает выполнения задачи, для обратных вызовов, установленных add_done_callback
, а также для любого вызова, вызывающего result()
в задаче. (Все это предусмотрено контрактом Future
, который Task
является подклассом.) Когда сопрограмма вызывает необработанное исключение, это исключение является просто еще одним результатом: когда кто-то ожидает задачу или вызывает result()
, исключение будет (повторно) вызвано тут же.
Это приводит к разнице между именованием и отсутствием именования объектов задачи. Если вы не укажете их имена, они будут уничтожены, как только событие l oop завершит их выполнение. В момент их уничтожения Python заметит, что никто никогда не обращался к их результату, и передаст его обработчику исключения. С другой стороны, если вы сохраните их в переменной, они не будут уничтожены, пока на них ссылается переменная, и не будет причин для вызова обработчика события l oop: насколько Python обеспокоен, вы можете решить вызвать .result()
для объектов в любой момент, получить доступ к исключению и обработать его в соответствии с вашей программой.
Чтобы устранить проблему, просто обработайте исключение самостоятельно, добавив try: ... except: ...
блок вокруг тела сопрограммы. Если вы не контролируете сопрограмму, вы можете вместо этого использовать add_done_callback()
для обнаружения исключения.