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

В asyncio, если корутина выбрасывает исключение, оно передаётся в тот код, который ожидает соответствующий future. Если await вызывается в нескольких местах, то каждое из них получит это исключение (так как оно сохраняется внутри объекта исключения). Следующий код напечатает сообщение об ошибке пять раз:

import asyncio

async def error():
await asyncio.sleep(1)
raise ValueError()

async def waiter(task):
try:
await task
except ValueError:
print('error')
else:
print('OK')

async def main():
task = asyncio.get_event_loop().create_task(error())

for _ in range(5):
asyncio.get_event_loop().create_task(waiter(task))

await asyncio.sleep(2)

loop = asyncio.get_event_loop()
loop.run_until_complete(main())


Если исключение выброшено, но задача (task) ни разу не была ожидаема (awaited), исключение будет потеряно. В таком случае при уничтожении задачи вы получите предупреждение: “Task exception was never retrieved”.

Когда вы используете await asyncio.gather(tasks) и одна из задач выбрасывает исключение, оно передаётся наружу. Однако если несколько задач выбросят исключения, вы получите только первое, остальные будут проигнорированы:

import asyncio

async def error(i):
await asyncio.sleep(1)
raise ValueError(i)

async def main():
try:
await asyncio.gather(
error(1),
error(2),
error(3),
)
except ValueError as e:
print(e)

loop = asyncio.get_event_loop()
loop.run_until_complete(main())


Вы можете использовать gather с параметром return_exceptions=True, чтобы получать исключения как обычные значения. Следующий код напечатает: [42, ValueError(2,), ValueError(3,)]

import asyncio

async def error(i):
await asyncio.sleep(1)
if i > 1:
raise ValueError(i)
return 42

async def main():
results = await asyncio.gather(
error(1),
error(2),
error(3),
return_exceptions=True,
)

print(results)

loop = asyncio.get_event_loop()
loop.run_until_complete(main())


👉 @BookPython
Просмотры: 1 000
Открыть в MAX Сообщить о неточности

Сообщить о неточности

Опишите, что нужно исправить. Если есть источник, добавьте ссылку.

Вы покидаете datool.ru

Ссылка ведёт на внешний сайт. datool.ru не отвечает за его содержимое — проверьте адрес, прежде чем вводить пароли или платёжные данные.

Переход через 10 с

Перейти