実現したいこと
【Python】class Aから他クラスのclass Bで実行中のプログラム処理を中断したい
前提
<添付プログラムの概要&やりたいこと>
1:処理を実行するカウントダウンの表示「中断ボタン → class Interruption()によって中断後の案内文が出る」
2:class Timeの処理が実行される「中断ボタン → class Interruption()によって中断後の案内文が出る」
3:処理終了後に画面を閉じるカウントダウンの表示
4:全プロセス終了
<<<【 質問理由・目的 】>>>
・class GUIのdef processingにおいて、中断ボタンが表示されます。そして、def processingでは他クラスであるclass Time()から呼び出し実行した2つの関数が処理されますが、処理中の任意のタイミングで中断ボタンを押すことでそれらの処理を中断したいです<上記2:の中断~に該当>
※仮にdef Time_sleepの処理が1日だった場合、やりたい処理は下記の通り
×「中断ボタン → def Time_sleepの処理後に中断:長い処理を中断させたいのに終わってからでは意味がないため」
〇「中断ボタン → def Time_sleepの処理中での中断し、Time_arg = Time()の処理自体を終了して次の処理を実行」
発生している問題・エラーメッセージ
<添付プログラムでの問題>:
①:def processingの時点でそもそも中断ボタンが押せなくなっている
②:問題①はthreading関数を用いて別スレッドでclass Time()を実行すれば中断ボタンを押せるようにはなる。しかし、class GUI上でのプロセスのみが無事に終了し、別スレッドであるclass Time()の関数たちは中断されず処理される。
該当のソースコード
Python(jupyter)
1import os 2import sys 3import time 4import tkinter as tk 5 6 7class Time: 8 def __init__(self): 9 self.Time_sleep() 10 self.Num_calc() 11 12 def Time_sleep(self): 13 time.sleep(100) # 100s 待機 14 15 def Num_calc(self): 16 for i in range(250000000): # 約5sの処理時間 17 pass 18 19 20class GUI: 21 def __init__(self): # 外枠となる設計図を作成 22 self.count = 3 23 24 self.root = tk.Tk() 25 self.root.geometry("1400x200") 26 self.integer_variable = tk.BooleanVar() 27 self.label = tk.Label(self.root, text="") 28 self.label.pack() 29 self.button = tk.Button(self.root, text="中断", command=self.end) 30 self.button.pack() 31 self.label.after(1, lambda: self.countdown(self.count, self.processing, True)) 32 33 def countdown(self, remaining, callback, coll): 34 if coll == False: 35 puo = "\n処理が完了しました" # \nは表示を真ん中にするための調整 36 pip = "閉じます" 37 38 self.button.pack_forget() 39 else: 40 puo = "処理を実行します" 41 pip = "開始" 42 43 if remaining <= 0: 44 callback() 45 else: 46 self.root.title("Backup") 47 self.label.configure( 48 text="{}:{}秒後に{}".format(puo, remaining, pip), font=("Helvetica", 20) 49 ) 50 self.root.after(1000, lambda: self.countdown(remaining - 1, callback, coll)) 51 52 def processing(self): 53 # ラベルを更新 54 self.label.configure(text="処理中です", font=("Helvetica", 20)) 55 self.root.update_idletasks() 56 57 Time_arg = Time() 58 59 self.countdown(5, self.end_taken, False) 60 61 def end(self): 62 self.integer_variable.set(False) 63 self.root.destroy() 64 65 def end_taken(self): 66 self.integer_variable.set(True) 67 self.root.destroy() 68 69 70class Interruption: 71 def __init__(self, app): 72 if app == False: 73 self.root = tk.Tk() 74 self.label = tk.Label( 75 self.root, 76 text="処理を中断しました\n再度処理を行いたい場合は下記のどちらかを実行してください", 77 font=("Helvetica", 20), 78 ).pack() 79 self.button = tk.Button( 80 self.root, text="Quit", command=self.root.destroy 81 ).pack() 82 else: 83 self.root = tk.Tk() 84 self.root.destroy() 85 86 87if __name__ == "__main__": 88 GUI = GUI() 89 GUI.root.mainloop() 90 91 num = GUI.integer_variable.get() 92 Interruption(num).root.mainloop()
試したこと
<調査・試したこと>
・thread関数による別スレッドの作成&実行
→ 問題②
参照したURL:
・https://www.pythontutorial.net/python-concurrency/python-stop-thread/
→ 解決の糸口になりそうなだと思ったURL。しかし、エラーが出て実行不可だった
・https://tsudango-tech.com/88/
・https://teratail.com/questions/76909
・https://magazine.techacademy.jp/magazine/22815
・https://www.pythontutorial.net/python-concurrency/python-stop-thread/
・https://docs.python.org/ja/3/library/threading.html>
・https://magazine.techacademy.jp/magazine/22221
・https://ja.stackoverflow.com/questions/89069/python%E3%81%AB%E3%81%8A%E3%81%84%E3%81%A6-threading%E3%83%9E%E3%83%AB%E3%83%81%E3%83%AC%E3%83%83%E3%83%89%E3%81%A8tkinter%E3%81%A7%E6%83%B3%E5%AE%9A%E9%80%9A%E3%82%8A%E3%81%AE%E5%8B%95%E4%BD%9C%E3%82%92%E3%81%97%E3%81%AA%E3%81%84
補足情報(FW/ツールのバージョンなど)
<補足>
・プログラミング勉強中の身であるため、不勉強な所がありますが今後のためにも何かあればご指摘をいただきたいです。
・試作中のため、変数名などは不適当な部分がありますがご容赦ください
・本問題が解決しなかった場合は、諸事情であまりやりたくなかったことですが、すべての処理を同一クラス内で処理することにします
・本プログラムのほとんどはBingのChatGPTで作成しております。不適切な部分や不具合などは自分のできる範囲で修正し、添付プログラムのようにコーディングしました。
「環境」
・Anaconda3、Windows11、jupyter notebook6.5.4、python 3.10.9

回答2件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2023/06/12 21:14