Как я могу зафиксировать все исключения из приложения wxPython?

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

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

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

Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
6
0
4 133
4
Перейти к ответу Данный вопрос помечен как решенный

Ответы 4

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

Ответ принят как подходящий

Для стандартного вывода журнала вы можете использовать оболочку 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

Ура, Дзинкс - в итоге я использовал комбинацию вашего предложения и монопокалипсиса.

Jon Cage 28.12.2008 13:14

Я пробовал делать это в своем приложении, чтобы перехватывать исключения и отображать понятные диалоговые окна ошибок, но это не сработало. Похоже, что из-за того, что wxPython порождает другой поток для App.MainLoop (), в этот момент исключения выходят за рамки блока try / except.

Soviut 04.01.2009 12:49

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

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

Ура, монопокалипсис - в итоге я использовал комбинацию вашего предложения и предложения Дзинкса. Хотел бы я принять оба ваших ответа!

Jon Cage 28.12.2008 13:15

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

sys.excepthook

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

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

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

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

Другие вопросы по теме