Как сказали @Denis и @lvo, link_exception
- это нормально, но я думаю, что был бы лучший способ для этого, не меняя текущий код на порождающий гринлет.
Обычно, когда исключениеброшенный в гринлет, метод _report_error
(в gevent.greenlet.Greenlet
) будет вызван для этого гринлета.Он будет выполнять некоторые вещи, такие как вызов всех функций связи и, наконец, вызов self.parent.handle_error
с exc_info из текущего стека.self.parent
здесь - глобальный объект Hub
, это означает, что все исключения, возникающие в каждом гринлете, всегда будут централизованы для одного метода обработки.По умолчанию 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, мы используем его для отправки информации об ошибках greenlet в sentry (система отслеживания исключений), пока она работает довольно хорошо.