過去の質問で参考になるもの→wxpythonでボタンなどからイベント実行後、GUIをフリーズさせたくない
◇キャンセルの要件によるのですが、
スクリプトを終了したい=sys.exit()
ならば、ボタン実行時の処理をTread
またはThreadPoolExecutor
に流す形にすれば良いかと。
要件が変わってsys.exit()
ではなく一連の処理(タスク)を途中でキャンセルしたくなったらProcessPoolExecutor
になります。
そして、ファイルの書き出し部分に関しては外部からキャンセルされてもファイル内容が破損しないように
tempファイルとos.replaceを使ったアトミックな書き出し処理に変更してくださいな。
厳密にキャンセルしている訳ではないですが、ブロッキングの方だけ回避する方法を。
1,executor.submitで別タスクを実行
2,閉じるボタンやexitボタンを押下した時は、画面を非表示(withdraw)にする。
以下のコードはmax_workers=1に指定しているので、並列度が1です、
この場合だと同じファイルでも並列に実行されることが起こりえないため問題ないかと。
ProcessPoolExecutorの
Python
1# -*- coding: utf-8 -*-
2from concurrent.futures import ThreadPoolExecutor, ProcessPoolExecutor, Future, as_completed
3from contextlib import closing
4from threading import current_thread, get_ident
5from random import randint
6import tkinter as tk
7import sys
8from time import sleep
9import requests
10
11
12def on_application_exit():
13 # Windowを閉じた時に行いたい処理
14 sys.exit(0)
15
16
17# max_workersは並列度
18executor = ProcessPoolExecutor(max_workers=1)
19
20
21def hard_task(url: str, seconds: int):
22 print(f'tid:{get_ident()}, {current_thread().getName()}, {seconds}')
23 sleep(seconds)
24 print(f'Wake up{seconds}')
25 r = requests.get(url)
26 # os.replaceを使ってアトミックに書き出してくださいな。
27 with open('yahoo.txt', 'a') as f:
28 f.write(r.text)
29
30
31class MyFrame(tk.Frame):
32 def __init__(self, root):
33 super().__init__(root)
34 self.pack()
35 self.btn_task = tk.Button(self, text='task', command=self.task)
36 self.btn_task.pack()
37 self.btn_exit = tk.Button(self, text='exit', command=on_application_exit)
38 self.btn_exit.pack()
39
40 def close(self):
41 self.master.withdraw()
42
43 def task(self):
44 seconds = randint(2, 5)
45 url = 'https://www.yahoo.co.jp'
46 task = executor.submit(hard_task, url, seconds)
47
48
49def main() ->None:
50 root = tk.Tk()
51 root.title("ProcessPoolExecutor")
52 root.protocol("WM_DELETE_WINDOW", on_application_exit)
53 root.geometry("400x200")
54 with closing(MyFrame(root)) as f:
55 root.mainloop()
56
57
58if __name__ == '__main__':
59 main()
60
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2018/05/06 09:50
2018/05/06 09:54
2018/05/06 10:02
2018/05/06 14:08