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

Posted

技术标签:

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

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

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

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

【问题讨论】:

【参考方案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。

【讨论】:

以上是关于如何从 wxPython 应用程序中捕获所有异常?的主要内容,如果未能解决你的问题,请参考以下文章

使用 openCV 和 wxPython 从网络摄像头获取流

捕获 WxPython 样式文本控件的回车键

如何捕获 Flex 中的所有异常?

Objective-C 在静态库中抛出异常。如何使用该库从程序中捕获异常?

在 C#.NET 中捕获所有未处理异常的简单方法

如何在Qt中捕获异常?