简体   繁体   English

如何在 Python/Asyncio 中处理未处理的异常?

[英]How to handle unhandled exception in Python/Asyncio?

I have a task.我有一个任务。

async def task():
    # stuff

I have my coroutine我有我的协程

async def coro(tasks):
    tasks = [asyncio.create_task(t) for t in tasks]
    task_iterator = tqdm(asyncio.as_completed(tasks), total=len(tasks))
    result = [await t for t in task_iterator]
    return result

I run it as我运行它

try:
    asyncio.run(coro)
except Exception as e:
    # handle error

The issue is that if task() fails, I get two errors.问题是如果task()失败,我会收到两个错误。 One error complains that unhandled exception in asyncio.run() shutdown task , and the other complains that task exception was never retrieved future .一个错误抱怨unhandled exception in asyncio.run() shutdown task另一个错误抱怨task exception was never retrieved future Both error messages point to something that happened in task() .两条错误消息都指向task()中发生的事情。

My questions are我的问题是

  1. Why does the try...except clause aorund asyncio.run() not catch these two issues?为什么try...except子句asyncio.run()没有捕捉到这两个问题?

  2. What can I do to catch them?我能做些什么来抓住他们?

  1. You're not running the coro in your main thread, but in the asyncio's runner.您不是在主线程中运行coro ,而是在 asyncio 的运行器中运行。 Each task (a function call with some arguments) is pushed to the back of an execute queue where they'll be popped once there's no other tasks executing.每个任务(带有一些参数的函数调用)都被推到执行队列的后面,一旦没有其他任务执行,它们就会被弹出。 Each task will leave the executing state as soon as it needs some I/O.每个任务一旦需要一些 I/O 就会离开执行状态。 There the task will be pushed to waiting queue and the if the asyncio's event loop catches the corresponding I/O action for that task it'll move the task to the executing queue.在那里,任务将被推送到等待队列,如果 asyncio 的事件循环捕获该任务的相应 I/O 操作,它会将任务移动到执行队列。 Summing up: While some tasks are waiting for I/O, other(s) can run the non-I/O parts.总结:当一些任务在等待 I/O 时,其他的可以运行非 I/O 部分。 That's why it's called async io .这就是为什么它被称为 async io

  2. You may use a decorator around the coro function and handle the exceptions there.您可以在coro函数周围使用装饰器并在那里处理异常。 Something like:就像是:

def exception_handler(f):
   async def wrapper(*args, **kwargs):
      try:
         return await f(*args, **kwargs)
      except Exception as e:
         print(e)
   return wrapper


@exception_handler
async def coro(tasks):
   ...


asyncio.run(coro, args=([1, 2, 3], ))

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM