在GUI中处理未处理的异常 [英] Handling unhandled exception in GUI

查看:99
本文介绍了在GUI中处理未处理的异常的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我主要是为精通技术的人们编写小型工具,例如程序员,工程师等。由于这些工具通常都是随着时间的推移而迅速改进的,所以我知道会有未处理的异常,并且用户不会介意。我希望用户能够向我发送回溯信息,以便我可以检查发生了什么并可能改善应用程序。

I am mostly writing a small tools for tech savvy people, e.g. programmers, engineers etc. As those tools are usually quick hacks improved over time I know that there are going to be unhandled exceptions and the users are not going to mind. I would like the user to be able to send me the traceback so I can examine what happened and possibly improve the application.

我通常会进行wxPython编程,但是我已经做了一些Java最近。我已经连接了 TaskDialog 类到 Thread.UncaughtExceptionHandler(),我对结果感到非常满意。特别是它可以捕获和处理来自任何线程的异常:

I usually do wxPython programming but I have done some Java recently. I have hooked up the TaskDialog class to the Thread.UncaughtExceptionHandler() and I am quite happy with the result. Especially that it can catch and handle exceptions from any thread:

我在wxPython中做了很长时间了。但是:

I was doing something similar in wxPython for a long time. However:


  1. 我不得不编写一个装饰器黑客程序,以便能够很好地打印来自另一个线程的异常。

  2. 即使功能正常,结果也很难看。

这是Java和wxPython的代码,因此您可以看到我所做的事情:

Here is the code for both Java and wxPython so you can see what I have done:

Java:

import java.awt.EventQueue;
import javax.swing.JFrame;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.JButton;
import java.awt.GridBagLayout;
import java.awt.GridBagConstraints;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;

import com.ezware.dialog.task.TaskDialogs;

public class SwingExceptionTest {

    private JFrame frame;

    public static void main(String[] args) {

        try {
            UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
        }
        catch (ClassNotFoundException e) {
        }
        catch (InstantiationException e) {
        }
        catch (IllegalAccessException e) {
        }
        catch (UnsupportedLookAndFeelException e) {
        }

        Thread.setDefaultUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
            public void uncaughtException(Thread t, Throwable e) {
                TaskDialogs.showException(e);
            }
        });

        EventQueue.invokeLater(new Runnable() {
            public void run() {
                try {
                    SwingExceptionTest window = new SwingExceptionTest();
                    window.frame.setVisible(true);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });
    }

    public SwingExceptionTest() {
        initialize();
    }

    private void initialize() {
        frame = new JFrame();
        frame.setBounds(100, 100, 600, 400);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        GridBagLayout gridBagLayout = new GridBagLayout();
        gridBagLayout.columnWidths = new int[]{0, 0};
        gridBagLayout.rowHeights = new int[]{0, 0};
        gridBagLayout.columnWeights = new double[]{0.0, Double.MIN_VALUE};
        gridBagLayout.rowWeights = new double[]{0.0, Double.MIN_VALUE};
        frame.getContentPane().setLayout(gridBagLayout);

        JButton btnNewButton = new JButton("Throw!");
        btnNewButton.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent arg0) {
                onButton();
            }
        });
        GridBagConstraints gbc_btnNewButton = new GridBagConstraints();
        gbc_btnNewButton.gridx = 0;
        gbc_btnNewButton.gridy = 0;
        frame.getContentPane().add(btnNewButton, gbc_btnNewButton);
    }

    protected void onButton(){
        Thread worker = new Thread() {
            public void run() { 
                throw new RuntimeException("Exception!");
            }
        };
        worker.start();
    }

}

wxPython:

import StringIO
import sys
import traceback
import wx
from wx.lib.delayedresult import startWorker


def thread_guard(f):
    def thread_guard_wrapper(*args, **kwargs) :
        try:
            r = f(*args, **kwargs)
            return r
        except Exception:
            exc = sys.exc_info()
            output = StringIO.StringIO()
            traceback.print_exception(exc[0], exc[1], exc[2], file=output)
            raise Exception("<THREAD GUARD>\n\n" + output.getvalue())
    return thread_guard_wrapper

@thread_guard
def thread_func():
    return 1 / 0

def thread_done(result):
    r = result.get()
    print r


class MainWindow(wx.Frame):
    def __init__(self, *args, **kwargs):
        wx.Frame.__init__(self, *args, **kwargs)

        self.panel = wx.Panel(self)
        self.button = wx.Button(self.panel, label="Throw!")
        self.button.Bind(wx.EVT_BUTTON, self.OnButton)

        self.sizer = wx.BoxSizer()
        self.sizer.Add(self.button)

        self.panel.SetSizerAndFit(self.sizer)  
        self.Show()

    def OnButton(self, e):
        startWorker(thread_done, thread_func)

app = wx.App(True)
win = MainWindow(None, size=(600, 400))
app.MainLoop()

现在的问题:

我可以轻松地在wxPython中做类似于Java解决方案的事情吗?或者,也许Java或wxPython中有更好的方法吗?

推荐答案

在Python中,您可以设置 sys.execpthook 到要为未捕获的异常调用的函数。然后,您将不需要装饰器,只需在钩子函数中集中处理异常即可。

In Python you can set sys.execpthook to a function that you want to be called for uncaught exceptions. Then you won't need the decorators, you can just deal with the exceptions centrally in your hook function instead.

而不是仅打印异常回溯文本并让其处理在股票标准输出窗口中显示时,您可以使用它执行更智能的操作,例如使用对话框显示文本并具有允许用户将错误信息发送回开发人员,忽略将来的错误,重新启动应用程序的控件。 ,或您想要的任何内容。

And rather than just printing the exception traceback text and letting it be displayed in the stock stdout window you can do something more intelligent with it, like using a dialog to display the text and have controls that allow the user to send the error information back to the developer, to ignore future errors, to restart the application, or whatever you want.

这篇关于在GUI中处理未处理的异常的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆