Как я могу зафиксировать все исключения из приложения wxPython?
-
03-07-2019 - |
Вопрос
Я пишу небольшое отладочное приложение для части комплекта, который мы разрабатываем, и я хотел бы распространить его среди нескольких пользователей, чтобы посмотреть, могут ли они спровоцировать какие-либо сбои.Кто-нибудь знает способ эффективной упаковки приложения wxPython для перехвата всех необработанных исключений, которые могут привести к сбою приложения?
В идеале я бы хотел записывать все выходные данные (а не только ошибки) и записывать их в файл.Любые необработанные исключения должны регистрироваться в текущем файле, а затем разрешать передачу исключения как обычно (т. е.процесс ведения журнала должен быть прозрачным).
Я уверен, что кто-то уже делал что-то в этом роде раньше, но мне не удалось найти в Google ничего, что выглядело бы полезным.
Решение
Для регистрации стандартного вывода вы можете использовать оболочку стандартного вывода, например, такую:
from __future__ import with_statement
class OutWrapper(object):
def __init__(self, realOutput, logFileName):
self._realOutput = realOutput
self._logFileName = logFileName
def _log(self, text):
with open(self._logFileName, 'a') as logFile:
logFile.write(text)
def write(self, text):
self._log(text)
self._realOutput.write(text)
Затем вам нужно инициализировать его в вашем основном файле Python (тот, который запускает все):
import sys
sys.stdout = OutWrapper(sys.stdout, r'c:\temp\log.txt')
Что касается регистрации исключений, самое простое - это обернуть метод MainLoop
файла wx.App в try..except, затем извлечь информацию об исключении, сохранить ее каким-либо образом, а затем повторно вызвать исключение с помощью повысить
, например:
try:
app.MainLoop()
except:
exc_info = sys.exc_info()
saveExcInfo(exc_info) # this method you have to write yourself
raise
Другие советы
Для обработки исключений, предположим, что ваш файл журнала открыт как журнал:
import sys
import traceback
def excepthook(type, value, tb):
message = 'Uncaught exception:\n'
message += ''.join(traceback.format_exception(type, value, tb))
log.write(message)
sys.excepthook = excepthook
Вы можете использовать
системный.excepthook
(см . Документы на Python)
и назначьте ему какой-нибудь пользовательский объект, который перехватывал бы все исключения, не обнаруженные ранее в вашем коде.Затем вы можете записать любое сообщение в любой файл, который пожелаете, вместе с traceback и делать все, что вам нравится, с исключением (перезапустить его, отобразить сообщение об ошибке и разрешить пользователю продолжать использовать ваше приложение и т.д.).
Что касается регистрации стандартного вывода - лучшим способом для меня было написать что-то похожее на OutWrapper от DzinX.
Если вы находитесь на стадии отладки, подумайте о том, чтобы удалять файлы журнала после каждой записи.Это сильно снижает производительность, но если вам удастся вызвать segfault в каком-то базовом коде C, ваши журналы не введут вас в заблуждение.
Есть разные способы. Вы можете поместить блок try..catch в wxApplication :: OnInit, однако это не всегда будет работать с Gtk. Р>
Хорошей альтернативой было бы переопределить Application :: HandleEvent в вашем производном классе wxApplication и написать такой код:
void Application::HandleEvent(wxEvtHandler* handler, wxEventFunction func, wxEvent& event) const
{
try
{
wxAppConsole::HandleEvent(handler, func, event);
}
catch (const std::exception& e)
{
wxMessageBox(std2wx(e.what()), _("Unhandled Error"),
wxOK | wxICON_ERROR, wxGetTopLevelParent(wxGetActiveWindow()));
}
}
Это пример C ++, но вы легко можете перевести на Python.