基于asyncio的库应提供什么API来处理严重错误? [英] What API should an asyncio based library provide for critical error handling?

查看:75
本文介绍了基于asyncio的库应提供什么API来处理严重错误?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I'm writing a library using asyncio. Under some circumstances it detects a ciritical error and cannot continue. It is not a bug, the problem has an external cause.

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

A regular library code would raise an exception. The program will terminate by default, but the caller also has a chance to catch the exception and perform a cleanup or some kind of reset. That is what I want, but unfortunately exceptions do not work that way in asyncio. More about that: https://docs.python.org/3/library/asyncio-dev.html#detect-never-retrieved-exceptions

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

What is a reasonable way to notify the async library user about the problem? Probably some callback activated when the error occurs. The user may do necessary cleanup and then exit in the callback.

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

But what should be the default action? Cancel the current task? Stop the entire event loop? Calling sys.exit?

推荐答案

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

In general, there should be no need for error-specific callbacks. Asyncio fully supports propagating exceptions across await boundaries inside coroutines, as well as across calls like run_until_complete where sync and async code meet. When someone awaits your coroutine, you can just raise an exception in the usual way.

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

One pitfall is with the coroutines that run as "background tasks". When such coroutines fail, potentially rendering the library unusable, no one will get notified automatically. This is a known deficiency in asyncio (see here for a detailed discussion), which is currently being addressed. In the meantime, you can achieve equivalent functionality with code like this:

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()。在这种设计中,库可能检测到错误状态并传播异常,或者主程序(大概是通过单独生成的协程)可以请求其干净退出。

work_forever is analogous to serve_forever, a call that can be awaited by a main() coroutine, or even directly passed to asyncio.run(). In this design the library may detect an erroneous state and propagate the exception, or the main program (presumably through a separately spawned coroutine) can request it to exit cleanly.

这篇关于基于asyncio的库应提供什么API来处理严重错误?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆