我正在使用asyncio
编写一个库。在某些情况下,它检测到严重错误并且无法继续。这不是错误,问题有外部原因。
常规库代码会引发异常。程序将默认终止,但调用者也有机会捕获异常并执行清理或某种重置。这就是我想要的,但不幸的是,异常在 asyncio 中不能以这种方式工作。更多相关内容: https://docs.python.org/3/library/asyncio-dev.html#detect-never-retrieved-exceptions
通知异步库用户有关问题的合理方法是什么?错误发生时可能会激活一些回调。用户可以进行必要的清理,然后在回调中退出。
但是默认操作应该是什么?取消当前任务?停止整个事件循环?调用sys.exit
?
最佳答案
一般来说,不需要特定于错误的回调。 Asyncio 完全支持跨协程内的 await
边界以及跨诸如同步和异步代码相遇的 run_until_complete
之类的调用传播异常。当有人等待你的协程时,你可以按照通常的方式引发异常。
一个陷阱是作为“后台任务”运行的协程。当此类协程失败时,可能会导致库无法使用,没有人会自动收到通知。这是 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/