正如@Denis 和@lvo 所说,没问题link_exception
,但我认为会有更好的方法,无需更改您当前的代码来生成greenlet。
通常,每当在 greenlet 中引发异常时,都会为该 greenlet 调用_report_error
方法 (in gevent.greenlet.Greenlet
)。它会做一些事情,比如调用所有的链接函数,最后,self.parent.handle_error
用当前堆栈中的 exc_info 调用。这里self.parent
是全局Hub
对象,这意味着每个greenlet中发生的所有异常都将始终集中到一个方法来处理。默认情况下Hub.handle_error
区分异常类型,忽略某些类型并打印其他类型(这是我们在控制台中经常看到的)。
通过修补Hub.handle_error
方法,我们可以轻松注册自己的错误处理程序,并且不再丢失错误。我写了一个辅助函数来实现它:
from gevent.hub import Hub
IGNORE_ERROR = Hub.SYSTEM_ERROR + Hub.NOT_ERROR
def register_error_handler(error_handler):
Hub._origin_handle_error = Hub.handle_error
def custom_handle_error(self, context, type, value, tb):
if not issubclass(type, IGNORE_ERROR):
# print 'Got error from greenlet:', context, type, value, tb
error_handler(context, (type, value, tb))
self._origin_handle_error(context, type, value, tb)
Hub.handle_error = custom_handle_error
要使用它,只需在初始化事件循环之前调用它:
def gevent_error_handler(context, exc_info):
"""Here goes your custom error handling logics"""
e = exc_info[1]
if isinstance(e, SomeError):
# do some notify things
pass
sentry_client.captureException(exc_info=exc_info)
register_error_handler(gevent_error_handler)
该解决方案已在 gevent 1.0.2 和 1.1b3 下进行了测试,我们使用它向 sentry(异常跟踪系统)发送 greenlet 错误信息,目前运行良好。