如何从wxPython应用程序捕获所有异常?

如何从wxPython应用程序捕获所有异常?,python,exception,error-handling,wxwidgets,error-reporting,Python,Exception,Error Handling,Wxwidgets,Error Reporting,我正在为我们正在开发的一些工具包编写一个调试应用程序,我想把它推出给一些用户,看看他们是否会引发任何崩溃。有人知道一种有效地包装wxPython应用程序的方法来捕获任何和所有可能导致应用程序崩溃的未处理异常吗 理想情况下,我希望捕获所有输出(不仅仅是错误)并将其记录到一个文件中。任何未经处理的异常都应该记录到当前文件,然后允许异常按照常规传递(即,记录过程应该是透明的) 我相信以前一定有人做过类似的事情,但我还没有通过谷歌找到任何有用的东西。有多种方法。您可以在wxApplication::On

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

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


我相信以前一定有人做过类似的事情,但我还没有通过谷歌找到任何有用的东西。

有多种方法。您可以在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。

< P>日志记录标准输出,可以使用一个STDUT包装器,例如:
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文件(运行所有内容的文件)中对其进行初始化:

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

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

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

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
你可以用

系统异常钩子

(见附件)

并为其分配一些自定义对象,这将捕获代码早期未捕获的所有异常。然后,您可以将任何消息记录到您想要的任何文件中,并进行回溯,并对异常执行任何您喜欢的操作(重新发送、显示错误消息并允许用户继续使用您的应用程序等)

至于日志stdout,对我来说最好的方法就是写一些类似于DzinX的Outrapper的东西


如果您处于调试阶段,请考虑在每个条目之后刷新日志文件。这对性能有很大的危害,但是如果您设法在一些底层C代码中造成segfault,您的日志不会误导您。

Cheers Dzinx-我最终使用了您的建议和Monocalypse的组合。我尝试在我的应用程序中这样做,以便捕获异常并显示友好的错误对话框,但没有成功。似乎是因为wxPython为App.MainLoop()生成了一个不同的线程,所以此时异常不在try/except块的范围内。我只希望我能接受你的两个答案!
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