2013-08-20 5 views
9

Я пытаюсь найти причину сбоя в наших скриптах python.Не удается найти источник исключения

Основная структура такова:

def main() 
    try: 
     dostuff 
    except Exception as ex: 
     import traceback 
     tb = traceback.format_exc() 
     import platform 
     node = platform.node() 
     sendMail([DEBUG_EMAIL], "Alarm exception on %s" % node, str(tb), []) 

Я получаю StackTrace в нашей основной обработки ошибок, не в электронном сообщении об ошибке, которое я должен.

Traceback (most recent call last): 
    File "/usr/lib/python2.6/logging/__init__.py", line 799, in emit 
    stream.write(fs % msg.encode("UTF-8")) 
UnicodeDecodeError: 'ascii' codec can't decode byte 0xc3 in position 66: ordinal not in range(128) 

Из того, что я вижу все записи-звонки в регистраторе находятся внутри примерки блока, но так как это не перехватываются и обрабатываются в моей электронной почте посылающего блок исключений, кажется, я что-то пропустил. Я проверил, и функция sendMail вообще не использует модуль регистрации. Поэтому исключение не должно происходить в моем исключающем блоке.

Я попытался добавить

sys.tracebacklimit = 10 

в верхней части файла увидеть, где исключение происходит, но это ничего не влияет. И теперь у меня нет идей о том, как найти причину возникновения проблемы.

Сценарий запускается один раз в час и только один раз падает в неделю, что заставляет меня предположить, что это связано с входными данными, но это обрабатывается только dostuff().

UPDATE:

Я понял, почему я получаю только одну строку StackTrace. Внутри emit() я нашел это.

 try: 
      ... doing stuff, something goes boom with encoding... 
     except UnicodeError: 
      stream.write(fs % msg.encode("UTF-8")) Here it goes Boom again 
     self.flush() 
    except (KeyboardInterrupt, SystemExit): 
     raise 
    except: 
     self.handleError(record) Which means it ends up here 

И соответствующая часть функции HandleError выглядит следующим образом:

ei = sys.exc_info() 
try: 
    traceback.print_exception(ei[0], ei[1], ei[2], None, sys.stderr) 

Что только печатает последнюю часть StackTrace.

+0

Я не уверен, что вы имеете в виду. – dutt

+0

Исключение похоже на скрипт '__init __. Py' пакета регистрации, так что это может произойти и при загрузке скрипта, и невозможен импорт' logging', прежде чем вы введете блок try – val

+0

@ValentinCLEMENT Добавлена ​​информация об использовании и частота аварий. – dutt

ответ

3

В основном ваша проблема двоякая

  1. Один поток журнала не принимает 8-битовые строки с расширенными символами, и бросает UnicodeError
  2. Существует глупая ошибка в модуле регистрации, которые делают его потерять первоначальные отслеживающий

точная причина исключения заключается в следующем:

>>> 'ä'.encode('UTF-8') 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
UnicodeDecodeError: 'ascii' codec can't decode byte 0xc3 in position 0: ordinal not in range(128) 

Но это исключение не является реальной проблемой. Это часть кода регистрации 2.6; 799 - последняя строка блока. Последняя строка вызывает проблему.В основном что-то регистрирует сообщение в 8-битной байтовой строке, кодированной UTF-8, содержащей расширенные буквы Latin-1; но потоку это не нравится, и бросает UnicodeError внутри блока try;

try: 
    if (isinstance(msg, unicode) and 
     getattr(stream, 'encoding', None)): 

     # .... the string is NOT an unicode instance, so ignored 
     # for brevity 
    else: 
     # this line throws the original exception 
     # fs is a bytestring "%s\n", and msg is a bytestring 
     # with extended letters, most probably Latin 1. 
     # stream.write spits out an UnicodeError on these values 
     stream.write(fs % msg) 
except UnicodeError: 
    # now we get a useless exception report from this code 
    stream.write(fs % msg.encode("UTF-8")) 

Так отладить это вы хотите установить точку останова на упомянутой выше линии 799, и попробовать все регистраторы, если они принимают следующую строку:

logging.getLogger(name).critical('Testing logger: ä') 

Если вы попали линии 799, то получить обратную сторону исключения, он может пролить свет на то, что происходит ...

+0

Хороший ответ :) За исключением того, что это происходит только один раз в неделю или около того, мне очень хотелось бы улучшить стек, чтобы увидеть, где в моем коде возникает проблема. Мой текущий план состоит в том, чтобы скопировать и изменить модуль протоколирования, чтобы исправить распечатку stacktrace. Затем, когда я знаю, откуда исходит ошибка, я могу вернуться к использованию стандартного модуля. – dutt