Как сделать так, чтобы программа на python'е продолжала работать после возникновения исключения, которое я не обработал? При этом желательно, чтобы выводился стек этого исключения.
> А ты всегда можешь сказать, где может возникнуть исключение?
Надо уметь определять.
По сабжу -- напиши кодогенератор, который преобразует твой код в что-то типа
try:
line1
except:
print_debug_info()
try:
line2
except:
.......
В нормальных языках такое легко реализовать с помощью макросов.
> Как сделать так, чтобы программа на python'е продолжала
> работать после возникновения исключения, которое я не обработал?
А с какого места она должна продолжить работу? Исключения возникают,
если произошла ошибка, и для корректного продолжения работы программы
нужно устранить последствия ошибки, обработав исключение.
А что за программа? Может быть подойдёт перезапуск? Что-то вроде:
while True:
try:
main()
break
except StandardError, exc:
вывод отладочной информации
>программа на python'е продолжала работать после возникновения исключения, которое я не обработал
Не делай этого. Если ты не знаешь, где исключение возникает, _перестарт_ программы в случае его возникновения - единственный реальный способ "продолжить" работу.
>Не делай этого. Если ты не знаешь, где исключение возникает, _перестарт_ программы в случае его возникновения - единственный реальный способ "продолжить" работу.
Не факт. Если функция не возвращает никаких значений ( в моём случае просто пишет в файл, отсутствие которого не фатально ), то программа спокойно продолжит свою работу. Это можно увидеть, если сделать try: ... except: pass. Ещё видел скрипт на питоне, который именно так обрабатывает "случайные" исключения м вполне сносно. Потерял скрипт к сожалению.
Так и отлавливай исключения в тех случаях, когда знаешь, что это не фатально. Такие места ты должен знать всегда. Они должны ещё при проектировании выявляться, как и места, где исключения фатальны.
Если ты этого не делал - выкинь весь свой код в топку, и пиши заново, на этот раз по человечески.
Вот функция для показа стека исключения, вызывается в 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 довольно опасна, потому как ты и знатьб не будешь о том что вот возникла какая то ошибка... очень черевато.
>Не факт... программа спокойно продолжит свою работу
Я тоже так думал. Пока не нарвался на непонятно откуда возникшее "MemoryError". После этого программа работает правильно очень недолго.
Т.о. ловить все исключения можно _только_ на небольших кусках некритичного нефункционального кода типа вывода журналов. Но поскольку они небольшие - их легко сделать надежными, тогда необходимость ловить все сама отпадет:-)
Типичный пример жизненно необходимого отлова исключений - какой нить сервис висящий в отдельной нити в бесконечном цикле. Неперехваченное исключение, связанное с тем что кто то из клиентов напр че нить криво записал куда нить приводит к падению всего приложения (сервера). Хотя он мог бы жить и жить себе...
Еще пример - передача данных из функции через исключение, иногда чильно упрощает код (когда надо передать че нить экстраординарное и хитрым образом его обрабоать, то что идет в разрез с типовым ретурном).
и тд и тп... Исключения ловить надо, токо с умом. А строка except : pass - это скрытый (отложенный для потомков или себя любимого) пипец... это да.
Ну батенька.... мемори еррор все таки скорее исключительное исключение (сорри за калмбур) чем правило... я таких еще не встречал.
А вот наоборот было часто - кривой клиент (один из дцати) и все летит нах....
Поставь
while True:
try: readThing()
except MemoryError, e : raise e
except: print_exc()
и будет тебе щастье...
Так их ловить надо сразу, в том месте, где можно их по делу отработать, а не вокруг большого куска кода. Например, не открылся файл - отрабатываем сразу, возвращаем отлуп клиенту (каковой отлуп должен быть предусмотрен протоколом), или, например, открываем для записи файл в tmp-пространстве, откладывая попытку записать куда попросили на потом.
И так - буквально в каждой строке кода надо делать. Кто не делает - урод.