Pythonアプリケーションをそのスレッドの1つから終了するにはどうすればよいですか?sys.exit()は、それが呼び出されたスレッドのみを終了するので、助けにはなりません。
Os.kill()ソリューションはあまりきれいではないので、使用したくありません。
メインスレッドを除くすべてのスレッドがデーモンである場合、最良のアプローチは一般的に thread.interrupt_main() -すべてのスレッドがそれを使用してメインスレッドでKeyboardInterrupt
を発生させることができます。通常は、メインスレッド(メインスレッドのファイナライザーが呼び出されるなどを含む)から適切にクリーンな終了につながる可能性があります。
もちろん、これによりプロセス全体が生き続けるデーモン以外のスレッドが発生する場合は、Markが推奨するようにos._exit
でフォローアップする必要がありますが、最後の手段として(kill -9
;-)それは物事をかなり荒々しく終了するためです(try/finally
ブロック、with
ブロック、atexit
関数などを含むファイナライザーは実行されません)。
短い答え: _os._exit
_ を使用してください。
例付きの長い答え:
DevShedのチュートリアル の単純なスレッドの例をヤンクして少し変更しました:
_import threading, sys, os
theVar = 1
class MyThread ( threading.Thread ):
def run ( self ):
global theVar
print 'This is thread ' + str ( theVar ) + ' speaking.'
print 'Hello and good bye.'
theVar = theVar + 1
if theVar == 4:
#sys.exit(1)
os._exit(1)
print '(done)'
for x in xrange ( 7 ):
MyThread().start()
_
sys.exit(1)
をコメントアウトしたままにすると、3番目のスレッドが出力された後にスクリプトが停止します。 sys.exit(1)
を使用してos._exit(1)
をコメントアウトすると、3番目のスレッドはnotprint _(done)
_を実行します、プログラムは7つのスレッドすべてを実行します。
_os._exit
_「通常、fork()の後の子プロセスでのみ使用する必要があります」-そして、別のスレッドが目的に十分に近い。また、そのマニュアルページの_os._exit
_の直後に列挙された値がいくつかあり、上記の例で使用したような単純な数値ではなく、_os._exit
_の引数として使用する必要があります。
thread.interrupt_main()
を使用すると、状況によっては役に立たない場合があります。 KeyboardInterrupt
sは、現在のコマンドを終了したり、入力行を削除したりするために、コマンドラインアプリケーションでよく使用されます。
加えて、 os._exit
は、コード内でfinally
ブロックを実行せずにプロセスを即座に強制終了します。これは危険な場合があります(たとえば、ファイルと接続は閉じられません)。
私が見つけた解決策は、カスタム例外を発生させるメインスレッドにシグナルハンドラを登録することです。バックグラウンドスレッドを使用して、シグナルを起動します。
import signal
import os
import threading
import time
class ExitCommand(Exception):
pass
def signal_handler(signal, frame):
raise ExitCommand()
def thread_job():
time.sleep(5)
os.kill(os.getpid(), signal.SIGUSR1)
signal.signal(signal.SIGUSR1, signal_handler)
threading.Thread(target=thread_job).start() # thread will fire in 5 seconds
try:
while True:
user_input = raw_input('Blocked by raw_input loop ')
# do something with 'user_input'
except ExitCommand:
pass
finally:
print('finally will still run')
関連する質問: