为什么通用“try / except”块不适用于 Python TkInter 回调?

Jam*_*mes 0 python tkinter

我已经确定,在 Python TkInter GUI 程序中,最佳实践是将整个内容包含在 try / except 块中,以便捕获所有异常并将其呈现给最终用户(而不是默默地出现问题或程序似乎无缘无故地退出)。

然而,这种方法存在一些问题。考虑以下小程序,当单击按钮时,该程序会尝试除以 0:

import tkinter

class Foo():
    def __init__(self):
        # Initialize a new GUI window
        root = tkinter.Tk()

        # The "Generic error" message is shown when the following is uncommented
        #number = 1 / 0

        # Define a button and draw it
        button = tkinter.Button(root, text='Generate an error', command=self.generate_error)
        button.pack()

        # Loop forever
        root.mainloop()

    def generate_error(self):
        # The "Generic error" message is not shown
        number = 1 / 0



if __name__ == '__main__':
    try:
        # Run the Foo class
        Foo()

    except Exception as e:
        print('Generic error:', str(e))
Run Code Online (Sandbox Code Playgroud)

为什么“一般错误”语句不适用于按钮回调函数?

Jam*_*mes 5

以下 StackOverflow 帖子很有帮助:Should I make SilentExceptions Louder in tkinter?

基本上,我需要使用report_callback_exception. 我相应地修改了代码片段:

import tkinter
import tkinter.messagebox
import traceback

class Foo():
    def __init__(self):
        # Initialize a new GUI window
        tkinter.Tk.report_callback_exception = callback_error  # TkInter callbacks run in different threads, so if we want to handle generic exceptions caused in a TkInter callback, we must define a specific custom exception handler for that
        root = tkinter.Tk()

        # The error() function is triggered when the following is uncommented
        #number = 1 / 0

        # Define a button and draw it
        button = tkinter.Button(root, text='Generate an error', command=self.generate_error)
        button.pack()

        # Loop forever
        root.mainloop()

    def generate_error(self):
        # The "callback_error()" function is triggered when the button is clicked
        number = 1 / 0


def error(message, exception):
    # Build the error message
    if exception is not None:
        message += '\n\n'
        message += traceback.format_exc()

    # Also log the error to a file
    # TODO

    # Show the error to the user
    tkinter.messagebox.showerror('Error', message)

    # Exit the program immediately
    exit()


def callback_error(self, *args):
    # Build the error message
    message = 'Generic error:\n\n'
    message += traceback.format_exc()

    # Also log the error to a file
    # TODO

    # Show the error to the user
    tkinter.messagebox.showerror('Error', message)

    # Exit the program immediately
    exit()



if __name__ == '__main__':
    try:
        # Run the Foo class
        Foo()

    except Exception as e:
        error('Generic error:', e)
Run Code Online (Sandbox Code Playgroud)