質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

Raspberry Pi

Raspberry Piは、ラズベリーパイ財団が開発した、名刺サイズのLinuxコンピュータです。 学校で基本的なコンピュータ科学の教育を促進することを意図しています。

Q&A

解決済

4回答

632閲覧

並列に実行してる複数のwhileループを止める方法を教えてください

ririkaru

総合スコア3

Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

Raspberry Pi

Raspberry Piは、ラズベリーパイ財団が開発した、名刺サイズのLinuxコンピュータです。 学校で基本的なコンピュータ科学の教育を促進することを意図しています。

0グッド

0クリップ

投稿2023/05/07 04:56

実現したいこと

並列に複数実行しているwhileループを ctrl+Cキーあるいは別のキーを入力すると停止するようにしたい
また、GPIOモジュールを使っているので 停止後に GPIO.cleanup() を実行したい

前提

whileループの入った複数のdef関数を threadingで同時に実行したいのですが
止め方がわかりません
処理すべてを一度に停止して、その後 GPIO.cleanup() を実行する方法を教えてください

該当のソースコード

python

1def loop_1 (): 2 while True: 3 ###省略 4 5def loop_2 (): 6 while True: 7 ###省略 8 9if __name__ == "__main__": 10 thread_1 = threading.Thread(target=loop_1) 11 thread_2 = threading.Thread(target=loop_2) 12 13 thread_1.start() 14 thread_2.start() 15

試したこと

python

1def loop_1 (): 2 while True: 3 try: 4 except KeyboardInterrupt: 5 break 6

KeyboardInterruptを実行しても
処理が続行してしまいます

補足情報(FW/ツールのバージョンなど)

環境 raspberrypi4bからThonny Python IDEで実行
(私はまだclassを理解できていないので
出来れば 使わないやりかたでお願いします)

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

dameo

2023/05/07 10:05

どちらも簡単ですが、KeyboardInterruptを受け取る方法と、スレッドを停止する方法はそれぞれ別の質問にすべきです。 それぞれ出来るようになってから、組み合わせを考えましょう。
guest

回答4

0

ベストアンサー

gloal 変数を参照してそのフラグがTrueになったら、スレッドを終了するようにしてはいかがでしょうか。
フラグは、シグナルハンドラー内でTrueにします。
シグナルハンドラーはSIGINTを捕捉します。
Clrl-C を押下するとSIGINTが発生します。
print("end")の箇所で、GPIO.cleanup()をすれば良いかと。
SIGINTの代わりにSIGUSR1などを使用しても構いません。(その場合はCtrl-Cでなく、SIGUSR1をこのプロセスに送出します)

python3

1import threading 2import signal 3G_flg = False 4def loop_1 (): 5 global G_flg 6 while True: 7 if G_flg == True: 8 print("loop_1") 9 break 10 ### 11 12def loop_2 (): 13 global G_flg 14 while True: 15 if G_flg == True: 16 print("loop_2") 17 break 18 ### 19 20def handler(signum,frame): 21 global G_flg 22 G_flg = True 23 print("handler",signum) 24 25 26if __name__ == "__main__": 27 signal.signal(signal.SIGINT, handler) 28 thread_1 = threading.Thread(target=loop_1) 29 thread_2 = threading.Thread(target=loop_2) 30 31 thread_1.start() 32 thread_2.start() 33 34 thread_1.join() 35 thread_2.join() 36 print("end") 37

投稿2023/05/07 07:02

tatsu99

総合スコア5438

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

すっごく単純だけど

Python

1import threading 2 3run = True 4 5def loop_1 (): 6 while run: 7 print(1) 8 print("1: terminated") 9 10def loop_2 (): 11 while run: 12 print(2) 13 print("2: terminated") 14 15if __name__ == "__main__": 16 thread_1 = threading.Thread(target=loop_1) 17 thread_2 = threading.Thread(target=loop_2) 18 19 thread_1.start() 20 thread_2.start() 21 input() # なんか入力したら 22 run = False # 止まる 23 print("bye.")

投稿2023/05/07 06:49

episteme

総合スコア16614

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

そもそもの考え方が逆です
ループを中断する方法、ではなく、
ループを中断できるようなコードを書く、ってことです。

実際の実装例は他の回答を参照。

投稿2023/05/07 10:58

y_waiwai

総合スコア87749

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

以下は ctypes.pythonapi.PyThreadState_SetAsyncExc() 使う方法です。

python

1import threading 2import ctypes 3import time 4 5def loop_1(): 6 try: 7 while True: 8 time.sleep(0.1) 9 except: 10 print('terminate loop1') 11 12def loop_2(): 13 try: 14 while True: 15 time.sleep(0.1) 16 except: 17 print('terminate loop2') 18 19def terminate_threads(*threads): 20 for th in threads: 21 tid = [tid for tid, thr in threading._active.items() if thr is th] 22 if tid: 23 ctypes.pythonapi.PyThreadState_SetAsyncExc( 24 ctypes.c_long(tid[0]), ctypes.py_object(ValueError)) 25 th.join() 26 27if __name__ == "__main__": 28 thread_1 = threading.Thread(target=loop_1) 29 thread_2 = threading.Thread(target=loop_2) 30 31 thread_1.start() 32 thread_2.start() 33 34 time.sleep(2) 35 terminate_threads(thread_1, thread_2)

投稿2023/05/07 08:09

編集2023/05/07 08:21
melian

総合スコア19714

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問