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

发布于 2024-07-06 19:22:53 字数 257 浏览 8 评论 0原文

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

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

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

I'm writing a little debug app for a bit of kit we're developing and I'd like to roll it out to a few users to see if they can provoke any crashes. Does anyone know a way of effectively wrapping a wxPython app to catch any and all unhandled exceptions that would cause the app to crash?

Ideally I'd want to capture all output (not just errors) and log it to a file. Any unhandled exceptions ought to log to the current file and then allow the exception to pass on as per usual (i.e. the logging process ought to be transparent).

I'm sure someone must have done something along these lines before, but I've not managed to turn up anything that looks useful via google.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

木格 2024-07-13 19:22:53

对于异常处理,假设您的日志文件打开为 log:

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

For the exception handling, assuming your log file is opened as log:

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
不语却知心 2024-07-13 19:22:53

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

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的code>MainLoop方法中的一个try..except,然后提取异常信息,以某种方式保存,然后通过raise重新引发异常,eg:

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

For logging standard output, you can use a stdout wrapper, such as this one:

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)

You then have to initialize it in your main Python file (the one that runs everything):

import sys    
sys.stdout = OutWrapper(sys.stdout, r'c:\temp\log.txt')

As to logging exceptions, the easiest thing to do is to wrap MainLoop method of wx.App in a try..except, then extract the exception information, save it in some way, and then re-raise the exception through raise, e.g.:

try:
    app.MainLoop()
except:
    exc_info = sys.exc_info()
    saveExcInfo(exc_info) # this method you have to write yourself
    raise
陈甜 2024-07-13 19:22:53

您可以使用

系统异常钩子

(请参阅 Python 文档

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

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

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

You can use

sys.excepthook

(see Python docs)

and assign some custom object to it, that would catch all exceptions not caught earlier in your code. You can then log any message to any file you wish, together with traceback and do whatever you like with the exception (reraise it, display error message and allow user to continue using your app etc).

As for logging stdout - the best way for me was to write something similar to DzinX's OutWrapper.

If you're at debugging stage, consider flushing your log files after each entry. This harms performance a lot, but if you manage to cause segfault in some underlying C code, your logs won't mislead you.

霊感 2024-07-13 19:22:53

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

There are various ways. You can put a try..catch block in the wxApplication::OnInit, however, that would not always work with Gtk.

A nice alternative would be to override the Application::HandleEvent in your wxApplication derived class, and write a code like this:

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

It's a C++ example, but you can surely translate to Python easily.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文