Asyncio собирать обработчик exception_handler не работает - PullRequest
0 голосов
/ 29 апреля 2020

Я пытаюсь использовать обработчик exception_handler вместе с asyncio.gather

Мой код:

import asyncio

def exception_handler(loop, context):
    print('Exception handler called')

async def coro():
    print("coro")
    raise RuntimeError("BOOM!")
    return 1

def main():
    loop = asyncio.get_event_loop()

    loop.set_exception_handler(exception_handler)
    group = asyncio.gather(coro(), coro(), coro())
    results = loop.run_until_complete(group)
    print(results)

main()

Когда я запускаю его, вместо того, чтобы получать обработчик исключений под названием, я получить:

Traceback (most recent call last):
  File "test.py", line 23, in <module>
    main()
  File "test.py", line 20, in main
    results = loop.run_until_complete(group)
  File "/usr/lib64/python3.7/asyncio/base_events.py", line 583, in run_until_complete
    return future.result()
  File "test.py", line 12, in coro
    raise RuntimeError("BOOM!")

1 Ответ

1 голос
/ 29 апреля 2020

Похоже, что в Python документах неясно, какие обработчики исключений asyncio должны обрабатывать.

По словам Python разработчика ядра Эндрю Светлова из этого сообщения об ошибке :

Обработчик исключений asyncio должен перехватывать только необработанные исключения, а не все сгенерированные.

[...] исключение из порожденной задачи не распространяется неявно на родительскую задачу. Вот почему исключение необработано и передано зарегистрированному обработчику исключений.

В отчете приводится следующий пример:

async def test():
    raise Exception("Something goes wrong")

async def main():
    #Un-comment either 1 of the following 3 lines
    # await test() # will not call exception_handler
    # await asyncio.gather(test()) # will not call exception_handler
    # asyncio.create_task(test()) # will call exception_handler

    await asyncio.sleep(5)

В вашем случае вы может обрабатывать исключения, как в любом синхронном коде:

import asyncio

async def coro():
    print("coro")
    raise RuntimeError("BOOM!")
    return 1

def main():
    loop = asyncio.get_event_loop()

    group = asyncio.gather(coro(), coro(), coro())
    try:
        results = loop.run_until_complete(group)
    except RuntimeError:
        # handle exception
    print(results)

main()
...