メインプログラムが終了したときにスレッドを終了するにはどうすればよいですか?


回答:


46

この質問を確認してください。正解は、スレッドを正しい方法で終了する方法についての優れた説明です。Pythonでスレッドを強制終了 する方法はありますか?

キーボード割り込み信号(ctrl + c)でスレッドを停止させるには、例外「KeyboardInterrupt」をキャッチし、終了する前にクリーンアップします。このような:

try:
    start_thread()  
except (KeyboardInterrupt, SystemExit):
    cleanup_stop_thread()
    sys.exit()

このようにして、プログラムが突然終了したときに何をするかを制御できます。

シグナルハンドラー(特定の場合はSIGINTシグナル)をセットアップできる組み込みのシグナルモジュールを使用することもできます:http//docs.python.org/library/signal.html


お返事ありがとうございます。私は質問を正しく述べていなかったかもしれません。その質問で与えられた例では、スレッドのstop()関数を実行する必要がありました。ctrl + Cでプログラムを異常終了すると、それは起こりません。したがって、私の質問は、「メインスレッドフローが中断された場合にmythread.stop()関数を呼び出すにはどうすればよいですか」というようなものです
facha 2010

1
であるcleanup_stop_thread()私が使用できるグローバル関数は?またはそれを実装する必要がありますか?
アルパー

@alper、多分それは何かを実装することが可能な単なる例だったと思います。あなたはそれを実装する必要があります
Leonardo Rick

98

ワーカースレッドをデーモンスレッドにすると、デーモン以外のスレッド(メインスレッドなど)がすべて終了したときにスレッドが停止します。

http://docs.python.org/library/threading.html#threading.Thread.daemon


4
シンプルで正確な答えをありがとう、デフォルトのthreading.ThreadデーモンのステータスisDaemon()はFalsesetDaemon(True)です。でTrueに設定してください。
トング

3
これは質問に答えて、うまくいきます。オペレーションは、一般的にスレッドをきれいに終了する方法を尋ねませんでした。
Johannes Overmann 2015

1
isDaemon()そしてsetDaemon()、古いゲッター/セッターです(上記のリンクされたドキュメントによる)、ちょうど使用daemon=Trueしてくださいthreading.Thread()
fabio.sang 2018

1
デーモンスレッドを使用すると、他の問題を引き起こし、あなたがここに欲しいものはおそらくないことに注意してください:stackoverflow.com/questions/20596918/...
Doopy

デーモンスレッドの使用を回避し、スレッドを完全に強制終了するには、stackoverflow.com / questions / 58910372
Pat-Laugh

14

サブスレッドをデーモンスレッドとして有効にしてみてください。

例えば:

推奨:

from threading import Thread

t = Thread(target=<your-method>)
t.daemon = True  # This thread dies when main thread (only non-daemon thread) exits.
t.start()

列をなして:

t = Thread(target=<your-method>, daemon=True).start()

古いAPI:

t.setDaemon(True)
t.start()

メインスレッドが終了すると(「Ctrl+を押すとC」)、他のスレッドも上記の手順で強制終了されます。


1
:デーモンスレッドを使用すると、他の問題を引き起こし、あなたがここに欲しいものはおそらくありませんことに注意してくださいstackoverflow.com/questions/20596918/...
Doopy

12

Pythonの標準ライブラリのatexitモジュールを使用して、メインスレッドの合理的に「クリーンな」終了時に(メインスレッドで)呼び出される「終了」関数を登録します。これには、などのキャッチされない例外が含まれKeyboardInterruptます。このような終了関数は(必然的にメインスレッドで!)stop必要な関数を呼び出すことができます。スレッドをとして設定する可能性とともに、daemon必要なシステム機能を適切に設計するためのツールを提供します。


このアプローチは、前2.6.5にPythonのバージョンでデーモン化スレッドを必要とせずに働いた。なお、答えはしてご覧くださいstackoverflow.com/questions/3713360/...。シャットダウン中のデーモンスレッドはpython3.4bugs.python.org/issue19466)より前は少し混乱しているため、これは残念なIMHOです。あなたが停止した場合、あなたのatexitハンドラーであなたのデーモンスレッドに参加し、すべてはあなたのスレッドのティアダウンをシリアライズする(おそらく重要でない)のコストで、問題ないはずです。
NeilenMarais 2015年

atexit.register()Pythonモジュールでの呼び出しが延期されたために奇妙なことが起こり、終了プロシージャがの後に実行される可能性があることに注意してくださいmultiprocessing。私はこの問題に対処する上で実行するQueuedaemon、スレッド:「EOFエラーを」マルチプロセッシングキューとスレッドを使用してプログラムの終了時に
デルガン2018年

どうやら、3.7.4以降などの最新バージョンのPythonでは、atexitデーモン以外のスレッドが動作していてメインスレッドが終了している場合、ハンドラーは呼び出されません。atexitを使用してスレッドを終了するときにスクリプトが終了時にスタックするを参照してください。
マーティ

9

あなたがそのようにスレッドをスポーンするなら---myThread = Thread(target = function)そしてそれからmyThread.start(); myThread.join()。CTRL-Cが開始されると、メインスレッドはそのブロッキングmyThread.join()呼び出しを待機しているため、終了しません。これを修正するには、.join()呼び出しにタイムアウトを設定するだけです。タイムアウトは必要なだけ長くすることができます。無期限に待機させたい場合は、99999のように非常に長いタイムアウトを設定しmyThread.daemon = Trueます。メインスレッド(デーモン以外)が終了するときにすべてのスレッドが終了するようにすることもお勧めします。


myThread.daemon = Trueこの問題の素晴らしい解決策です。
ブラノン2017

5
@Brannon.daemon=Trueは固溶体ではありません。説明については、このスレッドを確認してください:stackoverflow.com/a/20598791/5562492
Odyssee 2017年

2

デーモンスレッドは不正に強制終了されるため、ファイナライザー命令は実行されません。考えられる解決策は、無限ループではなくメインスレッドが動作しているかどうかを確認することです。

例:Python 3の場合:

while threading.main_thread().isAlive():
    do.you.subthread.thing()
gracefully.close.the.thread()

メインスレッドが別のスレッドからまだ生きているかどうかの確認を参照してください

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.