Скрученная необработанная ошибка - PullRequest
9 голосов
/ 06 августа 2011

Когда витой реактор работает и в отложенном состоянии возникает исключение, которое не перехвачено, на терминал выводится «Необработанная ошибка» вместе с отслеживанием и исключением. Можно ли обработать / перехватить эти исключения (например, установить обратный вызов или переопределить метод)?

РЕДАКТИРОВАТЬ: я знаю, что я могу поймать сбой, добавив errback к deferrerd. Я хочу знать, есть ли способ перехватить необработанный сбой / исключение, которое прошло по цепочке к реактору.

РЕДАКТИРОВАТЬ: По сути, мне интересно, есть ли у закрученного реактора глобальный обработчик ошибок или что-то, что может быть доступно. Мне интересно, потому что он печатает трассировку и ошибку от сбоя.

Пример:

Unhandled Error
Traceback (most recent call last):
  File "/var/projects/python/server.py", line 359, in run_server
    return server.run()
  File "/var/projects/python/server.py", line 881, in run
    reactor.run()
  File "/usr/local/lib/python2.6/dist-packages/Twisted-11.0.0-py2.6-linux-x86_64.egg/twisted/internet/base.py", line 1162, in run
    self.mainLoop()
  File "/usr/local/lib/python2.6/dist-packages/Twisted-11.0.0-py2.6-linux-x86_64.egg/twisted/internet/base.py", line 1171, in mainLoop
    self.runUntilCurrent()
--- <exception caught here> ---
  File "/usr/local/lib/python2.6/dist-packages/Twisted-11.0.0-py2.6-linux-x86_64.egg/twisted/internet/base.py", line 793, in runUntilCurrent
    call.func(*call.args, **call.kw)
  File "/var/projects/python/server.py", line 524, in monitor
    elapsed = time.time() - info.last
exceptions.NameError: global name 'info' is not defined

Ответы [ 3 ]

6 голосов
/ 06 августа 2011

Поскольку эти трассировки записываются с использованием вызова twisted.python.log.deferr() (в любом случае в Twisted 10.2), можно перенаправить их с помощью наблюдателя журнала.Это самая распространенная вещь, которую нужно делать с этими следами стека.Я не могу найти какой-либо базовый класс для наблюдателей журнала (на удивление), но есть встроенная пара:

twisted.python.log.PythonLoggingObserver - Все записанное идет в стандартный модуль Python logging.(Я использую это в своем приложении.)

twisted.python.log.FileLogObserver - Все записанные данные отправляются в файл.

Обе они будут отлавливать следы стека, сообщаемые реактором.Все, что вам нужно сделать, это построить обозреватель журнала (без аргументов) и затем вызвать метод start() объекта.

(Примечание: есть также класс StdioOnnaStick, который вы можете использоватьсоздайте и присвойте sys.stdout или sys.stderr, если хотите. Тогда все, что вы print отправите в журнал Twisted.)

На самом деле перехватите эти вызовы, так чтоследы стека никогда не регистрируются вообще, вы можете:

  • подкласс twisted.internet.SelectReactor и переопределить его runUntilCurrent() метод.Это то, что регистрирует следы стека.Вам нужно изучить источник twisted.internet.base.ReactorBase, прежде чем делать это.
  • После того, как вы выполните все операции импорта twisted.*, установите twisted.python.log.deferr на функцию по вашему выбору, которая совместима с прототипом def err(_stuff=None, _why=None, **kw).
3 голосов
/ 06 августа 2011

Вы можете добавить ошибку к отложенному;необработанные исключения автоматически преобразуются в twisted.python.failure.Failure.

1 голос
/ 06 августа 2011

Отвечая на ваш комментарий:

По сути, мне интересно, есть ли у закрученного реактора глобальный обработчик ошибок или что-то, к чему можно получить доступ.Я удивляюсь, потому что он печатает трассировку и ошибку от сбоя.

Ответ "не в надлежащем порядке".

Во-первых, реактор не имеет ничего общего с отложениями,фактически весь отсроченный модуль должен быть помещен в пакет twisted.python, но этого пока нельзя сделать из-за некоторых зависимостей.Возвращаясь к вашему вопросу ...

Копаясь в скрученном коде (подробнее, модуль twisted.internet.defer), вы можете описать следующий поток событий:

  1. Когда метод callback вызывается с результатом, отложенный экземпляр начинает выполнять свои обратные вызовы через метод _runCallbacks;
  2. Если один из обратных вызовов выдает исключение, онпереносится в Failure (строка 542 );
  3. Если цепь обратного вызова исчерпана, а последним результатом был сбой, текущий результат присваивается свойству failResult для DebugInfo экземпляр (строка 575 );
  4. Если отложенный экземпляр и, следовательно, его экземпляр DebugInfo являются сборщиком мусора, то в результате все еще существует активный сбой,вызывается метод DebugInfo.__del__ и выводится обратная связь.

С учетом этих предпосылок одним из простейших решений было бы обезьянское исправление класса DebugInfo:

from twisted.internet.defer import DebugInfo
del DebugInfo.__del__  # Hides all errors
...