Пост канала
Обработка исключений в асинхронных программах может быть непростой задачей. В 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
Открыть в MAX- Просмотры
- 1 151
- ER
- 0,6%
- Реакции
- 7