0
7

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

【Tkinter】Tkinterでtraceback表示したい!

Last updated at Posted at 2023-04-19

はじめに

tracebackをmessageboxに表示したい!
image.pngimage.png

Tkinterで作成したアプリケーションをexe化して完璧だと思った矢先、ユーザーによって予期せぬエラーを引き起こされる場合がある(知らんけど)

consoleウィンドウがあればtracebackを遡ってエラーを追求できるが、GUIのみの場合は何も起こらずエラーが出たのかすらわからない。

予測できるエラーに対してはtkinterのmessagebox.showerror()をif文とかで仕込んでおけばよいが、すべてのエラーに対して仕込むのは至難の業。

今回は、こんな風にtracebackの一部を表示し、
consoleがなくても「エラーやで」とわかってもらう方法をメモします。

発想

基本的な考え方は次の通りである。

  • try-except文を使ってエラーのときはmessagebox.showerror()を表示する
  • すべての動作にtry-except文を仕込むのはタルいので、デコレーターを作成しておく
  • tracebackライブラリを使ってエラー文をstrでゲットする

コード

GUIをに数字を入れるとその逆数を計算するプログラムです。
image.png
image.png

import tkinter as tk
from tkinter import messagebox

import traceback
from functools import wraps

# =============================================================================
# デコレータの定義
# =============================================================================
def show_on_error(function):
    "関数実行中に例外が発生したら、showerrorするデコレータ"
    @wraps(function)
    def show_error(*args,**kwargs):
        try:
            function(*args,**kwargs)
        except Exception as e:
            print(traceback.format_exc())
            title = e.__class__.__name__
            message = traceback.format_exc(limit=0)
            messagebox.showerror(f"{title}",
                                 f"{message}")
    return show_error

# =============================================================================
# GUIから呼び出される関数
# =============================================================================
@show_on_error
def calc(x):
    "いかにもエラーが出そうな関数"
    y = 1/float(x)
    messagebox.showinfo("ans",y)
    return y

# =============================================================================
# メイン処理
# =============================================================================
def main():
    "GUI作成"
    # ウィジェット定義
    root = tk.Tk()
    frame = tk.Frame(root,
                      padx=5,
                      pady=5)
    entry = tk.Entry(frame,
                      width=50)
    button = tk.Button(frame,
                        width=10,
                        text="button",
                        command=lambda:calc(entry.get()))
    
    # ウィジェット配置
    entry.grid(row=0,column=0)
    button.grid(row=0,column=1)
    frame.grid(row=0,column=0)
    root.mainloop()
    
    return

if __name__ == "__main__":
    main()

解説

モジュール

GUI作成に必要なモジュール

import tkinter as tk
from tkinter import messagebox

エラー文を取得するモジュール

import traceback

関数.__name__が正しく返ってくるようにするおまじない

from functools import wraps

デコレータ

デコレータshow_on_errorを定義します。

  • def
    show_on_error関数は引数に関数(function)取り、
    show_error関数でfunctionを実行する直前にtry-except文をかませる

  • try
    functionを実行し、エラーがあったらexcept文に飛ぶ

  • except
    まずはconsoleにprint(traceback.format_exc())でtracebackメッセージを出力する(printを使わずにtraceback.print_exc()でもOK)
    title = e.__class__.__name__で例外クラスの名前を取得
    message = traceback.format_exc(limit=0)でtracebackメッセージの最後の文を取得(limitの値を変えるとどこまで遡るかを変更できる)
    messagebox.showerror(f"{title}",f"{message}")でmessageboxを表示する

  • return
    return show_errorを書かないとcalc()を呼び出した際に'NoneType' object is not callableと怒られる

  • @wraps(function)関数.__name__が正しく返ってくるようにするおまじない

def show_on_error(function):
    "関数実行中に例外が発生したら、showerrorするデコレータ"
    @wraps(function)
    def show_error(*args,**kwargs):
        try:
            function(*args,**kwargs)
        except Exception as e:
            print(traceback.format_exc())
            title = e.__class__.__name__
            message = traceback.format_exc(limit=0)
            messagebox.showerror(f"{title}",
                                 f"{message}")
    return show_error

関数をデコレート

@show_on_errorcalc()関数をデコレート
x=0x="aaa"を代入するとそれぞれ別のエラーがポップアップする。
エラーが出なければ逆数を表示する

@show_on_error
def calc(x):
    "いかにもエラーが出そうな関数"
    y = 1/float(x)
    messagebox.showinfo("ans",y)
    return y

うまく行ったとき
image.png
エラーが出たとき
image.pngimage.png

GUIの作成

とりあえず構成だけ

root
└ frame
  ├ entry
  └ button
0
7
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
7

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?