Как я могу перехватить все исключения из приложения wxPython? - PullRequest
6 голосов
/ 03 октября 2008

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

В идеале я хотел бы захватить весь вывод (не только ошибки) и записать его в файл. Любые необработанные исключения должны регистрироваться в текущем файле и затем разрешать передачу исключения как обычно (т.е. процесс регистрации должен быть прозрачным).

Я уверен, что кто-то должен был что-то сделать в этом духе раньше, но мне не удалось найти что-нибудь полезное через Google.

Ответы [ 4 ]

10 голосов
/ 10 октября 2008

Для обработки исключений, при условии, что ваш файл журнала открыт как журнал:

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
6 голосов
/ 03 октября 2008

Для регистрации стандартного вывода вы можете использовать оболочку stdout, такую ​​как эта:

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, затем извлечь информацию об исключении, каким-то образом сохранить ее, а затем повторно вызвать исключение. до raise, например:

try:
    app.MainLoop()
except:
    exc_info = sys.exc_info()
    saveExcInfo(exc_info) # this method you have to write yourself
    raise
3 голосов
/ 17 декабря 2008

Вы можете использовать

sys.excepthook

(см. Документы Python )

и присвойте ему некоторый пользовательский объект, который бы перехватывал все исключения, которые ранее не были обнаружены в вашем коде. Затем вы можете записать любое сообщение в любой файл, который вы пожелаете, вместе с traceback и делать все, что вам угодно, за исключением (повторно поднять его, отобразить сообщение об ошибке и позволить пользователю продолжить использование вашего приложения и т. Д.).

Что касается записи stdout - лучший способ для меня - написать что-то похожее на OutWrapper DzinX.

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

1 голос
/ 03 октября 2008

Есть разные способы. Вы можете поместить блок 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.

...