我正在为我们正在开发的一些工具包编写一个小调试应用程序,我想将它推广给一些用户,看看他们是否会引发任何崩溃。有谁知道一种有效包装 wxPython 应用程序以捕获任何和所有会导致应用程序崩溃的未处理异常的方法?
理想情况下,我想捕获所有输出(不仅仅是错误)并将其记录到文件中。任何未处理的异常都应该记录到当前文件,然后允许异常照常传递(即记录过程应该是透明的)。
我确信以前一定有人做过类似的事情,但我没有设法通过谷歌找到任何看起来有用的东西。
我正在为我们正在开发的一些工具包编写一个小调试应用程序,我想将它推广给一些用户,看看他们是否会引发任何崩溃。有谁知道一种有效包装 wxPython 应用程序以捕获任何和所有会导致应用程序崩溃的未处理异常的方法?
理想情况下,我想捕获所有输出(不仅仅是错误)并将其记录到文件中。任何未处理的异常都应该记录到当前文件,然后允许异常照常传递(即记录过程应该是透明的)。
我确信以前一定有人做过类似的事情,但我没有设法通过谷歌找到任何看起来有用的东西。
对于异常处理,假设您的日志文件作为日志打开:
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
对于记录标准输出,您可以使用标准输出包装器,例如这个:
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')
至于记录异常,最简单的做法是将MainLoop
wx.App 的方法包装在 try..except 中,然后提取异常信息,以某种方式保存,然后通过 重新引发异常raise
,例如:
try:
app.MainLoop()
except:
exc_info = sys.exc_info()
saveExcInfo(exc_info) # this method you have to write yourself
raise
您可以使用
sys.excepthook
(见Python 文档)
并为其分配一些自定义对象,这将捕获代码中未捕获的所有异常。然后,您可以将任何消息记录到您希望的任何文件中,连同回溯,并对异常做任何您喜欢的事情(重新引发它,显示错误消息并允许用户继续使用您的应用程序等)。
至于记录标准输出——对我来说最好的方法是写一些类似于 DzinX 的 OutWrapper 的东西。
如果您处于调试阶段,请考虑在每个条目后刷新日志文件。这会极大地损害性能,但如果您设法在某些底层 C 代码中造成段错误,您的日志不会误导您。
有多种方式。您可以在 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。