Python Asyncio исключения, возникшие из loop.create_task () - PullRequest
1 голос
/ 16 апреля 2019

Я хочу, чтобы мой код использовал python logging для регистрации исключений. В моем обычном коде, использующем await, исключения вызываются нормально, поэтому:

try: await code_that_can_raise() except Exception as e: logger.exception("Exception happended")

Работает нормально.

Однако при использовании loop.create_task(coro())

Я не уверен, как я могу поймать исключение здесь.
Завершение вызова create_task (), очевидно, не сработает. Какое лучшее решение для регистрации каждого исключения в коде?

Ответы [ 2 ]

2 голосов
/ 16 апреля 2019

Как лучше всего регистрировать каждое исключение в коде?

Если вы контролируете вызов create_task, но не контролируете код в coro(), тогда вы можете написать оболочку регистрации:

def log_exceptions(awaitable):
    try:
        return await awaitable
    except Exception:
        logger.exception("Unhandled exception")

, тогда вы можете позвонить loop.create_task(log_exceptions(coro())).

Если вы не можете или не хотите обернуть каждую create_task, выможете вызвать loop.set_exception_handler, установив исключение для вашей собственной функции, которая будет регистрировать исключение по своему усмотрению.

1 голос
/ 16 апреля 2019

Только что было упомянуто: asyncio.Task объекты имеют методы result и exception.
result

[...] если сопрограмма вызвала исключение, это исключение поднятый [...]

exception:

[...] Если завернутая сопрограмма вызвала исключение, это исключение вернулся [...]

При простой настройке (в синтаксисе Python 3.7):

import asyncio
tasks =[]

async def bad_test():
    raise ValueError

async def good_test():
    return

async def main():
    tasks.append(asyncio.create_task(bad_test()))
    tasks.append(asyncio.create_task(good_test()))

asyncio.run(main())

Используя result, можно сделать:

for t in tasks:
    try:
        f = t.result()
    except ValueError as e:
        logger.exception("we're all doomed")

Или, используя exception:

for t in tasks:
    if isinstance(t.exception(), Exception):
        logger.exception("apocalypse now")

Однако оба метода требуют выполнения Task, в противном случае:

Если задача была отменена, этот метод вызывает CancelledError исключение.

( результат ): если результат Задачи еще не доступен, этот метод вызывает Исключение InvalidStateError.

( исключение ): если Задача еще не выполнена, этот метод вызывает исключение InvalidStateError.

Таким образом, в отличие от предложения в другом ответе, регистрация не будет происходить при возникновении исключений в задачах, а скорее, когда задачи оцениваются после их завершения.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...