我正在使用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/