Обработка исключения в асинхронном коде
import asyncio
async def producer(queue):
for i in range(7):
await queue.put(i)
await asyncio.sleep(0.2)
print('Producer Queue size:', queue.qsize())
async def consumer(queue):
try:
while True:
item = await queue.get()
await asyncio.sleep(0.3)
print(item)
if item is None:
print('Queue is empty')
queue.task_done()
break
if item == 3:
raise TypeError("Producer got exception")
queue.task_done()
print('Queue size:', queue.qsize())
except TypeError as e:
print(f'Error happened asf {e}')
queue.task_done()
raise e
async def main():
queue = asyncio.Queue()
producer_task = asyncio.create_task(producer(queue))
consumer_task = asyncio.create_task(consumer(queue))
# Запуск продюсера
await asyncio.gather(producer_task)
await queue.put(None)
# .join чтобы работало пока очередь непуста
await queue.join()
consumer_task.cancel() # Выход из цикла while
# Запуск consumer_task с возвратом ошибок
result = await asyncio.gather(consumer_task, return_exceptions=True)
print(result)
if __name__ == '__main__':
asyncio.run(main())
Пытаюсь отловить инициированную ошибку TypeError, но скрипт продолжает висеть и не могу понять где именно тонкое место. Приходится обращаться к коллективному разуму.
Ответы (1 шт):
Автор решения: diduk001
→ Ссылка
Чтобы обработать ошибку TypeError и продолжить исполнение, вы должны:
- Поместить обработку внутрь цикла
while - Убрать строчку
raise e
Также может возникать ошибка, связанная с тем, что вы не применяете оператор await к вызову корутины queue.put(None) в блоке "Запуск продюсера". Вот исправленная версия кода:
import asyncio
async def producer(queue):
for i in range(7):
await queue.put(i)
await asyncio.sleep(0.2)
print('Producer Queue size:', queue.qsize())
async def consumer(queue):
while True:
try:
item = await queue.get()
await asyncio.sleep(0.3)
print(item)
if item is None:
print('Queue is empty')
queue.task_done()
break
if item == 3:
raise TypeError("Producer got exception")
queue.task_done()
print('Queue size:', queue.qsize())
except TypeError as e:
print(f'Error happened asf {e}')
queue.task_done()
async def main():
queue = asyncio.Queue()
producer_task = asyncio.create_task(producer(queue))
consumer_task = asyncio.create_task(consumer(queue))
# Запуск продюсера
await asyncio.gather(producer_task)
await queue.put(None)
# .join чтобы работало пока очередь непуста
await queue.join()
consumer_task.cancel() # Выход из цикла while
# Запуск consumer_task с возвратом ошибок
result = await asyncio.gather(consumer_task, return_exceptions=True)
print(result)
if __name__ == '__main__':
asyncio.run(main())
Как упомянул @andreymal, чтобы прервать исполнение, вы должны убрать строчку await queue.join() в функции main и вкрнуть строчку raise e:
import asyncio
async def producer(queue):
for i in range(7):
await queue.put(i)
await asyncio.sleep(0.2)
print('Producer Queue size:', queue.qsize())
async def consumer(queue):
while True:
try:
item = await queue.get()
await asyncio.sleep(0.3)
print(item)
if item is None:
print('Queue is empty')
queue.task_done()
break
if item == 3:
raise TypeError("Producer got exception")
queue.task_done()
print('Queue size:', queue.qsize())
except TypeError as e:
print(f'Error happened asf {e}')
queue.task_done()
raise e
async def main():
queue = asyncio.Queue()
producer_task = asyncio.create_task(producer(queue))
consumer_task = asyncio.create_task(consumer(queue))
# Запуск продюсера
await asyncio.gather(producer_task)
await queue.put(None)
# .join чтобы работало пока очередь непуста
consumer_task.cancel() # Выход из цикла while
# Запуск consumer_task с возвратом ошибок
result = await asyncio.gather(consumer_task, return_exceptions=True)
print(result)
if __name__ == '__main__':
asyncio.run(main())