处理 GUI 中未处理的异常

2024-03-19

我主要是为精通技术的人编写一个小工具,例如由于这些工具通常是随着时间的推移而改进的快速黑客,我知道将会出现未处理的异常,并且用户不会介意。我希望用户能够向我发送回溯,以便我可以检查发生的情况并可能改进应用程序。

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

我很长一段时间都在 wxPython 中做类似的事情。然而:

  1. 我必须编写一个装饰器黑客才能很好地打印另一个线程的异常。
  2. 即使功能正常,结果也相当难看。

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

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到您想要为未捕获的异常调用的函数。那么你就不需要装饰器了,你可以在你的钩子函数中集中处理异常。

不仅仅是打印异常回溯文本并让它显示在库存标准输出窗口中,您还可以用它做一些更智能的事情,例如使用对话框来显示文本并具有允许用户将错误信息发送回的控件开发人员,忽略未来的错误,重新启动应用程序,或任何你想要的。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

处理 GUI 中未处理的异常 的相关文章

随机推荐

  • 元素数组中的 jQuery min/max 属性

    有没有一种简单的方法可以从 jQuery 元素数组中查找 min max 属性 我经常发现自己根据最小和最大对应项动态调整元素组的大小 大多数时候 这与元素的宽度和 或高度有关 但我确信这可以应用于元素的任何属性 我通常会做这样的事情 va
  • 使用 EncodePointer/DecodePointer 的好处

    使用有什么好处编码指针 解码指针在 Windows 中 MSDN say 对全局可用的指针进行编码有助于保护它们不被利用 这编码指针函数用秘密来混淆指针值 以便外部代理无法预测它 使用的秘密编码指针每个进程都不同 现在的问题是 如果攻击者位
  • C++ 中的动态树

    我想制作一棵树 每个节点都可以有一些子节点 但我不知道它们的数量 树必须在小内存中使用 无额外数据 以每个节点的恒定时间进行编码 我认为我将创建具有值和子属性 值是 int 子属性是堆栈 的类 Tree 以及指向该树中每个节点的指针数组 我
  • Retrofit2:预期为 BEGIN_ARRAY,但在第 1 行第 268 列路径 $[0].images 处为 STRING

    我知道这不是第一次有人问这个问题 但使用 Retrofit2 我找不到正确的解决方案来解决我的问题 我有一个包含字符串列表的对象 当我想将 JSON 响应转换为我的对象时 所有其他字段都可以 但在将字符串列表转换为我的列表时出现此错误 Re
  • 在 React 中使用共享 Worker

    我有一个后端应用程序 它不断地通过 Web 套接字向我的 React 应用程序提供事件 当收到特定事件时 应打开一个新的浏览器选项卡 该应用程序将由用户在多个选项卡中运行 因此我只需打开一个新选项卡一次 并防止所有正在运行的实例打开它 我尝
  • 如何使用 PHP 在 OS X 10.5.8 中启用 Sqlite3?

    我想在我的 MAMP 堆栈上安装 Symfony 框架 然而 当我尝试运行它时 Symfony 抱怨我需要 安装并启用 SQLite3 或 PDO SQLite 扩展 我不知道该怎么做 我安装了sqlite3 sqlite3 version
  • 通过网络复制文件(需要身份验证)

    是否有某种方法可以验证本地 非网络 用户身份 以便通过网络在 Net 中复制文件 net use不是一个选择 我似乎无法得到登录用户 http blogs msdn com shawnfa archive 2005 03 21 400088
  • Enum RadioButtonFor 编辑器模板设置值

    基于this https stackoverflow com questions 18542060 mvc4 enum and radio button list问题 我实现了一个 RadioButtonFor 编辑器模板 我工作得很好 但
  • text 或 ntext 数据类型上 REPLACE 的替代方案

    我需要更新 替换 datatable column 中的数据 该表有一个名为Content 我正在使用REPLACE功能 由于列数据类型是NTEXT SQL Server不允许我使用REPLACE功能 我无法更改数据类型 因为该数据库是第三
  • (Scp - 权限被拒绝(公钥)[关闭]

    Closed 这个问题不符合堆栈溢出指南 help closed questions 目前不接受答案 我正在尝试使用linux命令Scp获取服务器 xx xx xxx xx 的文件并将其放到我的桌面上 这是我的语法 scp email pr
  • Kubernetes docker 示例不公开端口

    当我探索 kubernetes 时 我从文档建议的基于 docker 的入门指南开始 该指南可以在这里找到 https github com GoogleCloudPlatform kubernetes blob release 1 0 d
  • NuGet 包如何包含 app.config 和 web.config 的转换?

    我正在尝试创建一个 nuget 包 它将添加 DLL 并在正确的配置文件中对其进行配置 该包可以在控制台 表单应用程序或 Web 应用程序中使用 因此我想更新适当的配置文件 app config 或 web config nu spec 文
  • Power Bi:如何参数化 Top N 视觉级别过滤器 [重复]

    这个问题在这里已经有答案了 Since PowerBI不支持Top N过滤page level 我想要使用 N 作为参数针对多个视觉效果立即更改它 是否可以 P S In 提供了更复杂情况的解决方案 最后本文 https www sqlbi
  • 为 Guzzle CookieJar 设置 cookie

    我正在 PHP 中为需要身份验证的网站进行单元测试 身份验证是基于 cookie 的 因此我需要能够将这样的 cookie 放入 cookie jar 中 user token gt 2c26b46b68ffc68ff99b453c1d30
  • 在android中添加横向方向和代码的最简单方法

    我是新来的android并想知道如何添加landscape模式在android谁能告诉我最简单的方法 我正在寻找一种非常简单的方法 如果您有此类问题 请查看下面的答案 谢谢 I have a simplest way to add a la
  • 远程创建 Akka Actor,无需新的 ActorSystem

    我已经仔细阅读了文档好几次了 http doc akka io docs akka 2 1 4 scala remoting html http doc akka io docs akka 2 1 4 scala remoting html
  • 实体框架 4.0 GetChanges() 等效项

    在 LINQ to SQL 中 您可以重写 SubmitChanges 并使用 this GetChangeSet 方法来获取所有插入 更新和删除 以便您可以在将更改提交到数据库之前进行最后一刻的更改 这可以在 EF 4 0 中完成吗 我看
  • RethinkDB:​​RqlRuntimeError:无法对序列序列执行括号

    给定表格中的以下文档 id d30aa369 99d6 4a40 9547 2cbdf0bb069a locations alerts person 200 person 300 name home alerts person 200 pe
  • 不会更新目标组件,但 工作正常[重复]

    这个问题在这里已经有答案了 我在让 Ajax 正常工作时遇到问题 在我这里的 xhtml 文件中 我使用 Ajax 来呈现一些启用或禁用的输入 并且它工作正常 然而 更进一步 我还使用 Ajax 来渲染包含的 xhtml 文件 其中包含其他
  • 处理 GUI 中未处理的异常

    我主要是为精通技术的人编写一个小工具 例如由于这些工具通常是随着时间的推移而改进的快速黑客 我知道将会出现未处理的异常 并且用户不会介意 我希望用户能够向我发送回溯 以便我可以检查发生的情况并可能改进应用程序 我通常做 wxPython 编