Начав программировать на Python, я чувствовал себя как дома с его сообщениями об ошибках. Теперь, когда вместо этого я программирую с помощью Tkinter, я обнаружил, что часто случается, что в моей программе есть ошибки, которые я не замечаю, даже если они генерируют исключение: я ловлю их (иногда) только потому, что я отлаживаю шаг за шагом Шаг (я использую wingIDE) и, например. в данной строке я вижу сообщение об исключении. Но что меня раздражает, так это то, что программа не останавливается, хотя это происходит даже в блоках не внутри try/error.
Если то, что я сказал, имеет какой-то смысл, знаете ли вы о каком-то общем подходе, по крайней мере, для отображения ошибок? Находясь в Tkinter, я мог создать окно ошибки и заполнить его любым возникающим исключением, когда это произойдет.
Ответ 2 · рейтинг 8 · ankostis
Как сказал @jochen-ritzel (Должен ли я сделать тихие исключения громче в tkinter?), есть tk.TK.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
Ответ 3 · рейтинг 1 · Yurii Rabeshko
Я предпочитаю явное расширение виджета Toplevel Tk, который представляет в основном главное окно приложения, а не внедрение хака:
import tkinter as tk
from tkinter import messagebox
class FaultTolerantTk(tk.Tk):
def report_callback_exception(self, exc, val, tb):
self.destroy_unmapped_children(self)
messagebox.showerror('Error!', val)
# NOTE: It's an optional method. Add one if you have multiple windows to open
def destroy_unmapped_children(self, parent):
"""
Destroys unmapped windows (empty gray ones which got an error during initialization)
recursively from bottom (root window) to top (last opened window).
"""
children = parent.children.copy()
for index, child in children.items():
if not child.winfo_ismapped():
parent.children.pop(index).destroy()
else:
self.destroy_unmapped_children(child)
def main():
root = FaultTolerantTk()
...
root.mainloop()
if __name__ == '__main__':
main()
ИМХО это выглядит как правильный путь.