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