20
17

More than 3 years have passed since last update.

tkinterを別スレッドで起動したときは、そのスレッド自身で停止処理して変数を後始末してからスレッド終了すること

Last updated at Posted at 2020-02-12

tkinterを別スレッドで起動した際、プログラムを正常終了させるのに苦労したので情報共有します。

tkinterはmainloop()を呼び出すことで、描画処理やイベント処理をループします。
tkinterのdestroy()を呼び出すことで、mainloop()を終了させることができます。
その後、スレッド終了する際にtkinterの破棄処理も行われます。

ただし、別スレッドから destroy() を呼び出したり、tkinterウィジェット(GUI部品)がインスタンス変数に代入されたままになっていたりすると、プログラムを正常終了することができませんでした。

サンプルプログラムで説明します。

import time
import threading
import tkinter as tk


class GUI:

    def start(self):
        self.running = True
        self.window = tk.Tk()
        self.window.title("Sample")
        self.window.geometry('320x240')

        self.value = tk.StringVar()
        entry = tk.Entry(textvariable=self.value)
        entry.pack()

        self.window.after(1000, self._check_to_quit)
        self.window.mainloop()
        # need to delete variables that reference tkinter objects in the thread
        del self.value
        del self.window

    def _check_to_quit(self):
        if self.running:
            self.window.after(1000, self._check_to_quit)
        else:
            self.window.destroy()

    def quit(self):
        self.running = False


def main():
    gui = GUI()
    thread = threading.Thread(target=gui.start)
    thread.start()

    time.sleep(2)
    for i in 1, 2, 3, 'ダー!!':
        gui.value.set(i)
        time.sleep(1)

    gui.quit()
    thread.join()

if __name__ == '__main__':
    main()

main()で、guiとサブスレッドを生成し、サブスレッドでgui.start()を起動しています。

main() 処理を終了する際、gui.quit()を呼び出して終了フラグをセットし、サブスレッドが1秒間隔でチェックして、サブスレッド自らがdestroy()を呼び出すようにしています。
この gui.quit() の代わりに、直接 gui.window.destroy() を呼び出すと無限ループに陥りました。
CTRL+Cもきかず、CTRL+\ で強制終了させる(コアダンプさせる)しかありませんでした。

サブスレッドでは、mainloop() から抜けてきた後、インスタンス変数を del しています。
この del 処理を行わないと、プログラムが異常終了(コアダンプ)したり、エラーメッセージを延々と出力し続けたりしました。

main()から直接gui.window.destroy()したり、インスタンス変数のdel処理をコメントアウトしたりして、何がおきるか実験してみてください。

tkinterとスレッドを併用する際には注意しましょう。

20
17
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
20
17