我已经确定,在 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)
为什么“一般错误”语句不适用于按钮回调函数?
以下 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)