Bubble up error from asyncio “create_task” in Python.

huangapple go评论53阅读模式
英文:

Bubble up error from asyncio "create_task" in Python

问题

以下是翻译好的部分:

我有一个可能会随机引发异常的长时间运行的任务。
这个任务是一个无限循环:不希望它完成或等待。它与特定类的一个实例绑定,当该实例被垃圾回收时,我取消了任务。

我希望在这个任务之外引发潜在的错误,但未能成功。

    def start_worker(self):
        self.worker = asyncio.create_task(
            self._worker()
        )
        def should_never_be_done(t: asyncio.Task):
            if t.exception() is not None:
                logger.exception(t.exception())
                raise t.exception()
            raise Exception(
                "_worker 任务已完成,但它不应该完成")
        self.worker.add_done_callback(should_never_be_done)

我在日志中看到了异常,但它并没有使整个应用程序崩溃,而我希望在这种情况下出现整体崩溃,而不是导致我的用户界面无限加载的静默失败。

英文:

I have a long running task that may raise an exception randomly.
This task is an infinite loop: it's not expected to finish or to be awaited. It is tied to an instance of a specific class, I cancel the task when the instance is garbage collected.

I'd like to raise potential errors "outside" of this task but failed to do so.

    def start_worker(self):
        self.worker = asyncio.create_task(
            self._worker()
        )
        def should_never_be_done(t: asyncio.Task):
            if t.exception() is not None:
                logger.exception(t.exception())
                raise t.exception()
            raise Exception(
                "_worker task is done, yet it should never finish")
        self.worker.add_done_callback(should_never_be_done)

I see the exception in my log, but it doesn't crash the whole app, which I want in this case instead of a silent fail leading to infinite loadings in my UI.

This related question show only how to log the error but do not aim at raising it, hence the separate question.

答案1

得分: 0

add_done_callback 很棒:如果在日志中看到异常,你已经捕获了异常 - 现在,只需按照你想要的方式处理它。

要么重新启动你的工作进程,要么创建一个事件或队列,通过它可以向应用程序的其余部分发出信号,告诉它们应该完成,或者,如果你只想让一切崩溃,就在这里关闭事件循环:

        ...
        def should_never_be_done(t: asyncio.Task):
            if t.exception() is not None:
                logger.exception(t.exception())
                # 灾难现场:
                asyncio.get_running_loop().close()
                
英文:

well, the add_done_callback is as good as it gets: if you see the exception in your logs, you had catch the exception - now, just do whatever you want with it.

Either just relaunch your worker, or create an event or queue with which you can sinalize to the rest of the application they should be done, or, to just crash everything, just close the event loop right there:

        ...
        def should_never_be_done(t: asyncio.Task):
            if t.exception() is not None:
                logger.exception(t.exception())
                # Trainwreck: 
                asyncio.get_running_loop().close()
                

huangapple
  • 本文由 发表于 2023年7月4日 23:41:54
  • 转载请务必保留本文链接:https://go.coder-hub.com/76614167.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定