Pythonのスレッドをデーモンにしよう
前回までのプログラムでは、ウィンドウの✕ボタンを押して中断すると、コンソールに以下のようなエラーが出力されてしまいます。
エラーメッセージ
RuntimeError: main thread is not in main loop
スレッドをデーモンにする
スレッドをデーモンにするには、スレッドを作成する時にdaemonオプションをTrueにします。
オブジェクト名 = threading.Thread(target=呼び出し可能オブジェクト, daemon=True)
注意
スレッドをデーモンにすることによって、このエラーメッセージを回避できます。
ただし、デーモンスレッドは終了時にファイルやDBなどのリソースを適切に開放しないため、重要なデータを扱うようなプログラムでは、スレッドをデーモンにすることは推奨しません。
スレッドをデーモンにするプログラム
スレッドをデーモンにするプログラムは、以下のようになります。
前回のプログラムとの違いは、34、35行目のスレッドの作成で、daemonオプションを追加したのみです。
プログラムの動きは、前回の記事を参照してください。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 |
### インポート import time import tkinter import threading ### 関数 def func(num, gap, pos_x, pos_y): ### 変数宣言 cnt = 0 ### 10未満の間ループ while cnt < 10: ### カウントアップ cnt += num ### キャンバス書き込み id = canvas.create_text(pos_x, pos_y, text=cnt, font=(None,48)) ### 待ち時間 time.sleep(gap) ### キャンバス初期化 canvas.delete(id) ### キャンバス作成 canvas = tkinter.Canvas(master=None, width=420, height=200) ### キャンバス表示 canvas.pack() ### スレッド作成 thread1 = threading.Thread(target=func, args=(1,1,140,100), daemon=True) thread2 = threading.Thread(target=func, args=(2,2,280,100), daemon=True) ### スレッド開始 thread1.start() thread2.start() ### イベントループ canvas.mainloop() |
上記のプログラムでは、ウィンドウの✕ボタンを押下した場合はエラーになりませんが、コンソールからCtrl-Cを押下して強制終了させた場合はエラーが出力されてしまいます。
このエラーを表示させたくない場合は、mainloop()を呼び出すところに、try~except文で例外処理(KeyboardInterrupt)を追加します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 |
### インポート import time import tkinter import threading ### 関数 def func(num, gap, pos_x, pos_y): ### 変数宣言 cnt = 0 ### 10未満の間ループ while cnt < 10: ### カウントアップ cnt += num ### キャンバス書き込み id = canvas.create_text(pos_x, pos_y, text=cnt, font=(None,48)) ### 待ち時間 time.sleep(gap) ### キャンバス初期化 canvas.delete(id) ### キャンバス作成 canvas = tkinter.Canvas(master=None, width=420, height=200) ### キャンバス表示 canvas.pack() ### スレッド作成 thread1 = threading.Thread(target=func, args=(1,1,140,100), daemon=True) thread2 = threading.Thread(target=func, args=(2,2,280,100), daemon=True) ### スレッド開始 thread1.start() thread2.start() ### 例外処理 try: ### イベントループ canvas.mainloop() ### キーボード割込み except KeyboardInterrupt: pass |