4

私はpythonプログラムを書いています。メイン関数で、継続的に実行されるスレッドを開始しています。スレッドを開始した後、メイン関数は while ループに入り、ユーザー入力を継続的に受け取ります。子スレッドで例外が発生した場合は、メイン関数も終了したいと考えています。それを行う最善の方法は何ですか?

前もって感謝します

4

2 に答える 2

7

親を「制御」するスレッドを持つことは、良い習慣ではありません。メインスレッドが開始するスレッドを管理/監視/制御する方が理にかなっています。

したがって、私の提案は、メイン スレッドが 2 つのスレッドを開始することです。既にあるスレッドは、ある時点で例外を終了/発生させ、もう 1 つはユーザー入力を読み取ります。メインスレッドはjoin、前者が終了するのを待ち ( s)、終了すると終了します。

from threading import Thread
import time

class ThreadA(Thread):
    def run(self):
        print 'T1: sleeping...'
        time.sleep(4)
        print 'T1: raising...'
        raise RuntimeError('bye')

class ThreadB(Thread):
    def __init__(self):
        Thread.__init__(self)
        self.daemon = True
    def run(self):
        while True:
            x = raw_input('T2: enter some input: ')
            print 'GOT:', x

t1 = ThreadA()
t2 = ThreadB()
t1.start()
t2.start()
t1.join()  # wait for t1 to finish/raise
print 'done'

ThreadB はデーモンであるため、明示的に停止させたり、参加させたりする必要はありません。メインスレッドが終了すると、それも終了します。

IMO、信号のような低レベルのものに頼る必要はありません。このソリューションでは、使用する必要さえありませんtry-except(ただし、正常に終了させるためにtry-exceptinが必要になる場合があります)。ThreadA

于 2013-05-11T06:41:52.930 に答える
4

Python では、シグナルモジュールを介してこのシステム コールにアクセスできるため、シグナル ハンドラを登録して、SIGINT好きなことを行うことができます。SIGINTちなみに、デフォルトのハンドラーは単純にKeyboardInterrupt例外を発生させるため、シグナルを使用したくない場合は、プログラム全体を try/except 構造に配置して、多かれ少なかれ同じ効果を得ることができます。子スレッドでのクラッシュ時にメイン スレッドを停止したいので、while ループ全体をexcept Exception:try-except ブロックに入れるだけです。

これは機能するはずですが、いくつかの背景情報-Pythonのシグナルモジュールのドキュメントには、複数のスレッドが実行されている場合、メインスレッド(つまり、プロセスの開始時に作成されたスレッド)のみがシグナルを受信すると明示的に記載されています(メインスレッドのシグナル)。そのため、シグナル ハンドラは 1 つのスレッドでのみ実行され、すべてのスレッドでは実行されません。シグナルに応答してすべてのスレッドを停止するには、メイン スレッドのシグナル ハンドラが他の子スレッドに停止メッセージを伝える必要があります。これはさまざまな方法で実行できますが、最も簡単な方法は、すべての子スレッドも参照を保持するブール変数の値をメイン スレッドで反転させることです。

于 2013-05-11T05:31:12.680 に答える