如何在tkinter中使无声的异常更大声?

时间:2011-01-22 22:17:10

标签: python exception user-interface tkinter warnings

如果我从终端运行以下代码,我会在终端中收到有用的错误消息:

import Tkinter as tk

master = tk.Tk()

def callback():
    raise UserWarning("Exception!")

b = tk.Button(master, text="This will raise an exception", command=callback)
b.pack()

tk.mainloop()

但是,如果我在没有终端的情况下运行它(例如,通过双击图标),则会禁止显示错误消息。

在我真实的,更复杂的Tkinter应用程序中,我喜欢GUI有点防撞击。我不喜欢我的用户很难给我有用的反馈来解决导致的意外行为。

我应该如何处理?有没有一种标准方法可以在Tkinter应用程序中公开回溯或stderror或诸如此类的东西?我正在寻找比尝试/除了无处不在的东西更优雅的东西。

编辑:Jochen Ritzel在下面给出了一个很好的答案,弹出一个警告框,并提到将它附加到一个班级。只是为了明确这一点:

import Tkinter as tk
import traceback, tkMessageBox

class App:
    def __init__(self, master):
        master.report_callback_exception = self.report_callback_exception
        self.frame = tk.Frame(master)
        self.frame.pack()
        b = tk.Button(
            self.frame, text="This will cause an exception",
            command=self.cause_exception)
        b.pack()

    def cause_exception(self):
        a = []
        a.a = 0 #A traceback makes this easy to catch and fix

    def report_callback_exception(self, *args):
        err = traceback.format_exception(*args)
        tkMessageBox.showerror('Exception', err)

root = tk.Tk()
app = App(root)
root.mainloop()

我仍然存在困惑:Jochen提到在不同的框架中具有不同的异常报告功能的可能性。我还没看到怎么做。这是显而易见的吗?

3 个答案:

答案 0 :(得分:23)

report_callback_exception执行此操作:

import traceback
import tkMessageBox

# You would normally put that on the App class
def show_error(self, *args):
    err = traceback.format_exception(*args)
    tkMessageBox.showerror('Exception',err)
# but this works too
tk.Tk.report_callback_exception = show_error

如果您没有将'Tkinter导入为tk',请执行

Tkinter.Tk.report_callback_exception = show_error

答案 1 :(得分:1)

首先是后续内容:就在今天,tkinter.Tk.report_callback_exception文档字符串的CPython tracker上的补丁明确指出Jochen's solution是有意的。在Windows上的pythonw下运行时,补丁也(并且主要)停止了对回调异常的崩溃。

第二:在没有控制台的情况下制作stderr函数的解决方案是一个简单的开头(这应该是一个单独的SO问题)。

import sys, tkinter

root = tkinter.Tk()

class Stderr(tkinter.Toplevel):
    def __init__(self):
        self.txt = tkinter.Text(root)
        self.txt.pack()
    def write(self, s):
        self.txt.insert('insert', s)

sys.stderr = Stderr()

1/0 # traceback appears in window

需要更多操作才能使弹出窗口保持隐藏直到需要,然后使其可见。

答案 2 :(得分:0)

我在寻求解决同一问题时发现了这个螺纹。我必须根据当前的tkinter版本方法进行一些修改。我还添加了一个自定义的错误消息处理程序,因为我发现用户不知道Tk错误消息的含义。

在课程的__init__中包括:

parent.report_callback_exception = self.report_callback_exception

然后在您的Tk课中:

    def report_callback_exception(self, exc, val, tb):
        #Handles tkinter exceptions
        err_msg = {'Index 0 out of range': 'None found'}
        try:
            err = err_msg[str(val)]
        except KeyError:
            err = 'Oops, try again'
        messagebox.showerror('Error Found', err)

您可以扩展err_msg词典以包含您想要的其他任何内容。在我的情况下,我正在根据Entry对象构建可搜索的数据库,因此,如果用户键入了数据库中不存在的字符串,则会给用户一种简单的语言错误。