【问题标题】:Catch MainLoop exceptions and displaying them in MessageDialogs捕获 MainLoop 异常并在 MessageDialogs 中显示它们
【发布时间】:2010-09-29 08:35:39
【问题描述】:

我有一个依赖外部配置文件的 wxPython 应用程序。如果有任何配置错误,我想提供友好的消息对话框。我试图通过将我的 app.MainLoop() 调用包装在 try/except 语句中来完成这项工作。

下面的代码适用于我的 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()

我读过一些关于可以在 wx.App 类中重写的 OnExceptionInMainLoop 方法的内容,但我读到的源代码必须是过时的(2004 年),因为 wx.App 似乎不再有这样的方法名字。

编辑:

我需要能够在我的主循环期间捕获未处理的异常,以便我可以进一步处理它们并将它们显示在错误对话框中,而不是静默传递,也不会终止应用程序。

sys.excepthook 解决方案级别太低,不能很好地与 wxPython 主循环线程配合使用。虽然指向另一个答案的链接执行相同的尝试/除了环绕主循环,但由于 wxPython 再次为 app/ui 生成不同的线程而无法正常工作。

【问题讨论】:

    标签: python exception-handling wxpython wxwidgets


    【解决方案1】:

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

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

    【讨论】:

    • 我在 wxPython 应用程序中遇到了非常相似的问题。我不能在 wx.App 中使用“redirect=True”(如在 Chandler 项目中),因为我需要在控制台窗口中使用 sys.stdoutOnExceptionInMainLoop 似乎又回到了 wxPython 2.9 中,但它仍然是测试版,我不能要求客户安装它。覆盖“sys.excepthook”以弹出自定义对话框并进行自定义日志记录对我来说效果很好。
    【解决方案2】:

    我为Chandler 编写了类似的代码,其中任何未处理的异常都会弹出一个包含堆栈和其他信息的窗口,用户可以放入额外的 cmets(当它发生时他们做了什么等)并提交给钱德勒开发商。有点像Mozilla Talkback(我相信nowadays他们使用Breakpad)功能。

    要在 wxPython 中执行此操作,您需要向 wx.App 提供重定向参数。这将弹出wx.PyOnDemandOutputWindow(您可能希望覆盖它以提供更好看的实现)。

    Chandler 中的相关源文件在这里:

    • Chandler.py 启动应用程序并设置重定向属性,并在正常应用程序启动失败时尝试捕获并显示错误对话框
    • Application.py自定义应用对象,包括设置我们自定义的wx.PyOnDemandOutputWindow
    • feedback.py 有自定义 wx.PyOnDemandOutputWindow 的实现;它还需要 feedback.xrc 和 feedback_xrc.py

    【讨论】:

    • 不幸的是,“钱德勒”的链接已经失效。
    【解决方案3】:

    也许this 问题可能有用,它会尝试捕获所有异常。

    【讨论】:

    • 请注意,该示例将 app.MainLoop() 包装在 try/except 中。这不起作用,至少在我的任何尝试中都不起作用。
    【解决方案4】:

    发布对我来说非常相似的问题的解决方案。

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

    【讨论】:

      【解决方案5】:

      使用sys.excepthook 对我来说很好。

      我发现以下文章对我有很大帮助:wxPython: Catching Exceptions from Anywhere

      【讨论】:

        猜你喜欢
        • 2018-02-12
        • 2011-11-14
        • 1970-01-01
        • 2017-12-27
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多