我正在使用asyncio编写一个库。在某些情况下,它会检测到致命错误,因此无法继续。这不是错误,问题可能是由外部原因引起的。

常规库代码将引发异常。该程序将默认终止,但调用方也有机会捕获异常并执行清除或某种重置。这就是我想要的,但是不幸的是,异常在asyncio中无法正常工作。有关更多信息:
https://docs.python.org/3/library/asyncio-dev.html#detect-never-retrieved-exceptions

有什么合理的方法可以通知异步库用户有关该问题的信息?错误发生时可能激活了一些回调。用户可以进行必要的清理,然后退出回调。

但是默认 Action 应该是什么?取消当前任务?停止整个事件循环?调用sys.exit吗?

最佳答案

通常,不需要特定于错误的回调。 Asyncio完全支持在协程内部跨await边界以及跨同步和异步代码相遇的调用(如run_until_complete)的传播异常。当有人在等待您的协程时,您可以按照通常的方式提出异常(exception)。

一个陷阱是作为“后台任务”运行的协程。当这样的协程失败时,可能会使该库无法使用,则不会自动通知任何人。这是asyncio中的一个已知缺陷(有关详细讨论,请参见here),当前是being addressed。同时,您可以使用以下代码实现等效的功能:

class Library:
    async def work_forever(self):
        loop = asyncio.get_event_loop()
        self._exit_future = loop.create_future()
        await self._exit_future

    async def stop_working(self):
        self._cleanup()
        self._exit_future.set_result(None)

    async def _failed(self):
        self._cleanup()
        self._exit_future.set_exception(YourExceptionType())

    def _cleanup(self):
        # cancel the worker tasks
        ...
work_forever serve_forever 类似,main()协程可以等待该调用,甚至可以直接将其传递给asyncio.run()。在这种设计中,库可能检测到错误状态并传播异常,或者主程序(大概是通过单独生成的协程)可以请求其干净退出。

关于python - 基于asyncio的库应提供什么API来处理严重错误?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/53676088/

10-12 23:12