2016-05-27 5 views
0

私は、Python TkInter GUIプログラムでは、すべての例外をキャッチしてエンドユーザーに提示するために、try/exceptブロックに全体を囲むことがベストプラクティスであることを確認しました。プログラムは一見何の理由もありません)。一般的な "try/except"ブロックがPython TkInterコールバックに適用されないのはなぜですか?

ただし、このアプローチにはいくつかの問題があります。ボタンがクリックされたときに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)) 

なぜ「一般的なエラー」の文は、ボタンのコールバック関数には適用されませんか?

+1

エラーを生成するコードは 'try'ブロックに含まれていないためです。つまり、 'Foo()'を呼んでも例外は発生しません。 – kindall

+0

あなたのコメントは不明です。すべてを包括的なtry/exceptブロックに囲む適切な方法を示すためにコードスニペットを修正できますか? – James

+0

UIレイヤーはスレッドを使用するため、ほぼ確実です。他のスレッドの例外は、メインスレッドに伝播されません。 –

答えて

2

次StackOverflowのポストは参考になりました:Should I make silent exceptions 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) 
関連する問題