LINUX.ORG.RU

Python: обработка исключений


0

0

Как сделать так, чтобы программа на python'е продолжала работать после возникновения исключения, которое я не обработал? При этом желательно, чтобы выводился стек этого исключения.

★★★

Ответ на: комментарий от Debiloid

>А ты их обрабатывай.

А ты всегда можешь сказать, где может возникнуть исключение? Обрабатываю, насколько могу.

zenith ★★★
() автор топика
Ответ на: комментарий от zenith

> А ты всегда можешь сказать, где может возникнуть исключение?

Надо уметь определять.

По сабжу -- напиши кодогенератор, который преобразует твой код в что-то типа 

try:
  line1
except:
  print_debug_info()
  try:
     line2
  except:
     .......

В нормальных языках такое легко реализовать с помощью макросов.

nsav-ng
()

> Как сделать так, чтобы программа на python'е продолжала
> работать после возникновения исключения, которое я не обработал?

А с какого места она должна продолжить работу? Исключения возникают,
если произошла ошибка, и для корректного продолжения работы программы
нужно устранить последствия ошибки, обработав исключение.

А что за программа? Может быть подойдёт перезапуск? Что-то вроде:

while True:
  try:
    main()
    break
  except StandardError, exc:
    вывод отладочной информации

DKorolkov
()
Ответ на: комментарий от zenith

Всегда, конечно же.

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

Debiloid
()

>программа на python'е продолжала работать после возникновения исключения, которое я не обработал

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

DonkeyHot ★★★★★
()
Ответ на: комментарий от DonkeyHot

>Не делай этого. Если ты не знаешь, где исключение возникает, _перестарт_ программы в случае его возникновения - единственный реальный способ "продолжить" работу.

Не факт. Если функция не возвращает никаких значений ( в моём случае просто пишет в файл, отсутствие которого не фатально ), то программа спокойно продолжит свою работу. Это можно увидеть, если сделать try: ... except: pass. Ещё видел скрипт на питоне, который именно так обрабатывает "случайные" исключения м вполне сносно. Потерял скрипт к сожалению.

zenith ★★★
() автор топика
Ответ на: комментарий от zenith

Так и отлавливай исключения в тех случаях, когда знаешь, что это не фатально. Такие места ты должен знать всегда. Они должны ещё при проектировании выявляться, как и места, где исключения фатальны.

Если ты этого не делал - выкинь весь свой код в топку, и пиши заново, на этот раз по человечески.

Debiloid
()

Вот функция для показа стека исключения, вызывается в except-e или после. код несколько заморочный потому как пишет стек в логи и тд, но идея в общес ясна.

def bug_report():
if sys.exc_info() != (None,None,None) : last_type, last_value, last_traceback = sys.exc_info()
else : last_type, last_value, last_traceback = sys.last_type, sys.last_value, sys.last_traceback
tb, descript = last_traceback, []
while tb :
fname, lno = tb.tb_frame.f_code.co_filename, tb.tb_lineno
descript.append('\tFile "%s", line %s, in %s\n'%(fname, lno, tb.tb_frame.f_code.co_name))
tb = tb.tb_next
descript.append('%s : %s\n'%(last_type.__name__, last_value))
for i in descript : print >> server.LOGS, i,

В принципе если есть такая прабла - забирай майн в трай и вперед. Но учти, обработака вида except : pass довольно опасна, потому как ты и знатьб не будешь о том что вот возникла какая то ошибка... очень черевато.

AIv ★★★★★
()
Ответ на: комментарий от AIv

сорри, еще раз с номаным форматированием

def bug_report():
    if sys.exc_info() != (None,None,None) : last_type, last_value, last_traceback = sys.exc_info()
    else : last_type, last_value, last_traceback = sys.last_type, sys.last_value, sys.last_traceback 
    tb, descript = last_traceback, []
    while tb :
        fname, lno = tb.tb_frame.f_code.co_filename, tb.tb_lineno
        descript.append('\tFile "%s", line %s, in %s\n'%(fname, lno, tb.tb_frame.f_code.co_name))
        tb = tb.tb_next
    descript.append('%s : %s\n'%(last_type.__name__, last_value))
    for i in descript : print >> server.LOGS, i,

AIv ★★★★★
()
Ответ на: комментарий от Debiloid

>Если ты этого не делал - выкинь весь свой код в топку, и пиши заново, на этот раз по человечески.

Тон сбавь.

zenith ★★★
() автор топика
Ответ на: комментарий от AIv

>Но учти, обработака вида except : pass довольно опасна.

Да я знаю :) Просто в качестве примера привёл.

За bug_report() спасибо.

zenith ★★★
() автор топика
Ответ на: комментарий от Debiloid

Очень содержательный у Вас ник... отражает сущность владельца на все 200 процентов.

AIv ★★★★★
()
Ответ на: комментарий от zenith

>Не факт... программа спокойно продолжит свою работу

Я тоже так думал. Пока не нарвался на непонятно откуда возникшее "MemoryError". После этого программа работает правильно очень недолго.

Т.о. ловить все исключения можно _только_ на небольших кусках некритичного нефункционального кода типа вывода журналов. Но поскольку они небольшие - их легко сделать надежными, тогда необходимость ловить все сама отпадет:-)

DonkeyHot ★★★★★
()
Ответ на: комментарий от Debiloid

О чем и речь. (try:...; except: pass) на больших кусках кода _не_ увеличивает надежность. Нужно другими способами пользоваться.

DonkeyHot ★★★★★
()
Ответ на: комментарий от DonkeyHot

re

Э... несоглашуся я.

Типичный пример жизненно необходимого отлова исключений - какой нить сервис висящий в отдельной нити в бесконечном цикле. Неперехваченное исключение, связанное с тем что кто то из клиентов напр че нить криво записал куда нить приводит к падению всего приложения (сервера). Хотя он мог бы жить и жить себе...

Еще пример - передача данных из функции через исключение, иногда чильно упрощает код (когда надо передать че нить экстраординарное и хитрым образом его обрабоать, то что идет в разрез с типовым ретурном).

и тд и тп... Исключения ловить надо, токо с умом. А строка except : pass - это скрытый (отложенный для потомков или себя любимого) пипец... это да.

AIv ★★★★★
()
Ответ на: re от AIv

>Типичный пример жизненно необходимого отлова исключений - какой нить сервис висящий в отдельной нити в бесконечном цикле.

Во-во. Именно на таком я и прокололся недавно:-) Вылезла MemoryError именно в таком вот месте. Проблема где-то в другом, но оно проявилось именно в:

while True:

try: readThing()

except: print_exc()

И процесс, вместо быть перезапущеным "монитором" 2е суток бессмыслено тыкается в ту же ошибку.

DonkeyHot ★★★★★
()
Ответ на: комментарий от DonkeyHot

Ну батенька.... мемори еррор все таки скорее исключительное исключение (сорри за калмбур) чем правило... я таких еще не встречал.

А вот наоборот было часто - кривой клиент (один из дцати) и все летит нах....

Поставь

while True: 
   try: readThing()
   except MemoryError, e : raise e 
   except: print_exc() 


и будет тебе щастье...

AIv ★★★★★
()
Ответ на: re от AIv

Так их ловить надо сразу, в том месте, где можно их по делу отработать, а не вокруг большого куска кода. Например, не открылся файл - отрабатываем сразу, возвращаем отлуп клиенту (каковой отлуп должен быть предусмотрен протоколом), или, например, открываем для записи файл в tmp-пространстве, откладывая попытку записать куда попросили на потом.

И так - буквально в каждой строке кода надо делать. Кто не делает - урод.

Debiloid
()
Ответ на: комментарий от Debiloid

В каждой строке

> И так - буквально в каждой строке кода надо делать.

В том числе для строк внутри except :). Рекурсивно :))).

DKorolkov
()
Ответ на: комментарий от DonkeyHot

Это там где вылетает мемори еррор. Что вообще говоря само по себе не есть хороший симптом - что то не ладно в Датском королевстве...

AIv ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.