Перехват исключений MainLoop и отображение их в MessageDialogs
-
03-07-2019 - |
Вопрос
У меня есть приложение wxPython, которое использует внешний файл конфигурации.Я хочу предоставить дружественные диалоговые окна с сообщениями, которые отображаются в случае каких-либо ошибок конфигурации.Я попытался реализовать эту работу, обернув вызов app.MainLoop() в оператор try/Exception.
Приведенный ниже код работает для кода инициализации в моем классе фрейма MainWindow, но не улавливает никаких исключений, возникающих в MainLoop.Как я могу перехватить и эти исключения?
if __name__ == '__main__':
app = MyApp(0)
try:
MainWindow(None, -1, 'My Cool App')
app.MainLoop()
except ConfigParser.Error, error_message:
messagebox = wx.MessageDialog(None, error_message, 'Configuration Error', wx.OK | wx.ICON_ERROR)
messagebox.ShowModal()
Я читал некоторые упоминания о методе OnExceptionInMainLoop, который можно переопределить в классе wx.App, но прочитанный мной источник должен быть устаревшим (2004 г.), поскольку у wx.App больше нет метода с таким именем.
РЕДАКТИРОВАТЬ:
Мне нужно иметь возможность перехватывать необработанные исключения во время основного цикла, чтобы я мог их обрабатывать и отображать в диалоговых окнах ошибок, а не передавать их автоматически и не завершать приложение.
Решение sys.Exceptionhook слишком низкоуровневое и плохо работает с потоком основного цикла wxPython.Хотя ссылка на другой ответ делает то же самое, попробуйте/за исключением переноса вокруг основного цикла, который, опять же, не работает из-за того, что wxPython создает другой поток для приложения/UI.
Решение
Я закодировал что-то вроде этого для Чендлер, где при любых необработанных исключениях появляется всплывающее окно со стеком и другой информацией, и пользователи могут оставлять дополнительные комментарии (что они делали, когда это произошло и т. д.) и отправлять их разработчикам Chandler.Немного похоже на Обратная связь Mozilla (настоящее время я думаю, они используют функцию Breakpad, если хотите.
Чтобы сделать это в wxPython, вам необходимо предоставить параметр перенаправления в wx.App.Это появится wx.PyOnDemandOutputWindow (вы, вероятно, захотите переопределить его, чтобы обеспечить более красивый вид реализации).
Соответствующие исходные файлы в Чендлере находятся здесь:
- Чендлер.py запускает приложение и устанавливает атрибут перенаправления, а также пытается перехватить и отобразить диалоговые окна ошибок в случае сбоя нормального запуска приложения.
- Приложение.py настраивает объект приложения, включая настройку нашего индивидуального wx.PyOnDemandOutputWindow
- обратная связь.py имеет реализацию настроенного wx.PyOnDemandOutputWindow;дополнительно потребуются файлы Feedback.xrc и Feedback_xrc.py.
Другие советы
Не знаю, сработает ли это для приложения wxPython, но в модуле sys вы можете перезаписать атрибут исключения, который представляет собой функцию, вызываемую с тремя аргументами: (type, value, traceback)
, когда перехватывается необработанное исключение.Вы можете установить туда свою собственную функцию, которая обрабатывает только те исключения, которые вам нужны, и вызывать исходную функцию для всех остальных.
Проконсультируйтесь: http://docs.python.org/library/sys.html#sys.excepthook
Возможно этот вопрос может быть полезен, он пытается уловить все исключения.
Публикация решения, которое помогло мне с очень похожей проблемой.
import wx
import sys
import traceback
class Frame(wx.Frame):
def __init__(self):
wx.Frame.__init__(self, None)
panel = wx.Panel(self)
m_close = wx.Button(panel, -1, "Error")
m_close.Bind(wx.EVT_BUTTON, self.OnErr)
def OnErr(self, event):
1/0
def handleGUIException(exc_type, exc_value, exc_traceback):
err_msg = ''.join(traceback.format_exception(exc_type, exc_value, exc_traceback))
err_msg += '\n Your App will now terminate'
# Here collecting traceback and some log files to be sent for debugging.
# But also possible to handle the error and continue working.
dlg = wx.MessageDialog(None, err_msg, 'Termination dialog', wx.OK | wx.ICON_ERROR)
dlg.ShowModal()
dlg.Destroy()
sys.exit()
sys.excepthook = handleGUIException
if __name__ == '__main__':
app = wx.App(redirect=False)
top = Frame()
top.Show()
app.MainLoop()
С использованием sys.excepthook
мне очень хорошо.
Я считаю следующую статью очень полезной: вксПитон:Перехват исключений откуда угодно.