【问题标题】:How can I capture all exceptions from a wxPython application?如何从 wxPython 应用程序中捕获所有异常?
【发布时间】:2010-09-15 00:53:38
【问题描述】:

我正在为我们正在开发的一些工具包编写一个小调试应用程序,我想将它推广给一些用户,看看他们是否会引发任何崩溃。有谁知道一种有效包装 wxPython 应用程序以捕获任何和所有可能导致应用程序崩溃的未处理异常的方法?

理想情况下,我希望捕获所有输出(不仅仅是错误)并将其记录到文件中。任何未处理的异常都应该记录到当前文件,然后允许异常照常传递(即记录过程应该是透明的)。

我确信以前一定有人做过类似的事情,但我没有设法通过谷歌找到任何看起来有用的东西。

【问题讨论】:

    标签: python exception error-handling wxwidgets error-reporting


    【解决方案1】:

    对于异常处理,假设您的日志文件以日志形式打开:

    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
    

    【讨论】:

    • 干杯 monopocalypse - 我最终结合了你的建议和 Dzinx 的建议。我只希望我能接受你的两个答案!
    【解决方案2】:

    对于记录标准输出,您可以使用标准输出包装器,例如这个:

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

    关于记录异常,最简单的做法是把wx.App的MainLoop方法包裹在try..except中,然后提取异常信息,以某种方式保存,然后重新引发异常通过raise,例如:

    try:
        app.MainLoop()
    except:
        exc_info = sys.exc_info()
        saveExcInfo(exc_info) # this method you have to write yourself
        raise
    

    【讨论】:

    • Cheers Dzinx - 我最终结合了你的建议和 monopocalypse 的建议
    • 我尝试在我的应用程序中执行此操作以捕获异常并显示友好的错误对话框,但它不起作用。似乎因为 wxPython 为 App.MainLoop() 生成了一个不同的线程,所以此时异常超出了 try/except 块的范围。
    【解决方案3】:

    你可以使用

    sys.excepthook

    (见Python docs

    并为其分配一些自定义对象,这将捕获代码中未捕获的所有异常。然后,您可以将任何消息记录到您希望的任何文件中,连同回溯并做任何您喜欢的异常(重新引发它、显示错误消息并允许用户继续使用您的应用等)。

    至于记录标准输出 - 对我来说最好的方法是编写类似于 DzinX 的 OutWrapper 的东西。

    如果您处于调试阶段,请考虑在每次输入后刷新日志文件。这会极大地损害性能,但如果您设法在某些底层 C 代码中造成段错误,您的日志不会误导您。

    【讨论】:

      【解决方案4】:

      有多种方法。您可以在 wxApplication::OnInit 中放置一个 try..catch 块,但是,这并不总是适用于 Gtk。

      一个不错的选择是在 wxApplication 派生类中覆盖 Application::HandleEvent,并编写如下代码:

      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。

      【讨论】:

        猜你喜欢
        • 2018-04-03
        • 2019-03-02
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2010-09-10
        • 1970-01-01
        • 2015-11-30
        • 1970-01-01
        相关资源
        最近更新 更多