捕获MainLoop异常并在MessageDialogs中显示它们

问题描述:

我有一个wxPython应用程序依赖于外部配置文件。我想提供友好的消息对话框,显示是否有任何配置错误。我试图通过在try/except语句中包装我的app.MainLoop()调用来完成这项工作。捕获MainLoop异常并在MessageDialogs中显示它们

下面的代码适用于我的MainWindow框架类中的init代码,但不会捕获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() 

我读过,可在wx.App类中重写的OnExceptionInMainLoop方法的一些提及,但我读的源必须是过时(2004年)以来wx.App似乎不再有这个名字的方法。

编辑:

我需要能够赶上未处理的异常,我的主循环中,这样我可以进一步处理他们,在错误对话框显示出来,而不是默默传递,而不是终止应用程序。

sys.excepthook解决方案太低级别,并与wxPython主循环线程打不开。虽然到另一个答案的链接做了相同的尝试/除了包装在主循环中不能正常工作,wxPython再次为app/ui产生了一个不同的线程。

我为Chandler编写了这样的代码,其中任何未处理的异常都会弹出一个包含堆栈和其他信息的窗口,并且用户可以添加其他注释(它们在发生什么时发生等)并将其提交给Chandler开发人员。有点像Mozilla Talkbacknowadays他们使用Breakpad我相信)功能,如果你愿意。

要在wxPython中执行此操作,您需要为wx.App提供重定向参数。这会弹出wx.PyOnDemandOutputWindow(你可能想重写它以提供更好看的实现)。

钱德勒相关的源文件所在的位置:

  • Chandler.py启动应用程序,并设置重定向属性,以及试图赶上和的情况下,显示错误对话框正常的应用程序启动失败
  • Application.py定制应用程序对象(包括设置我们的定制wx.PyOnDemandOutputWindow)将为定制的wx.PyOnDemandOutputWindow;实现自定义wx.PyOnDemandOutputWindow;其中包含自定义wx.PyOnDemandOutputWindow;它还需要feedback.xrc和feedback_xrc.py

不知道这是否适用于wxPython应用程序,但是在sys模块中,您可以覆盖excepthook属性,该属性是一个函数,该函数使用3个参数(type, value, traceback)调用,当发生uncaugth异常时。你可以在那里安装你自己的函数,只处理你想要的异常,并为所有其他函数调用原始函数。

咨询:http://docs.python.org/library/sys.html#sys.excepthook

+0

我有一个wxPython应用程序非常类似的问题。我无法在_wx.App_中使用“redirect = True”(因为在Chandler项目中),因为我需要在控制台窗口中使用_sys.stdout_。 _OnExceptionInMainLoop_似乎回到了wxPython 2.9,但它仍然是测试版,我不能要求客户端安装它。重写“sys.excepthook”弹出一个自定义对话框,自定义日志记录对我来说工作得很好。 – bitman 2012-08-23 07:42:17

也许this问题可能是一些使用的,它试图捕获所有异常。

+1

请注意,该示例正在将app.MainLoop()封装在try/except中。这不起作用,至少在我的任何尝试中都没有。 – Soviut 2009-01-03 19:06:30

发布解决方案,为我工作的一个非常类似的问题。

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()