並行して実行する一連のタスクがありますが、それらの最後に、いずれかのスレッドが例外をスローしたかどうかを知る必要があります。例外を直接処理する必要はありません。スレッドの1つが例外で失敗したかどうかを知る必要があるだけなので、スクリプトをクリーンに終了できます。
簡単な例を次に示します。
#!/usr/bin/python
from time import sleep
from threading import Thread
def func(a):
for i in range(0,5):
print a
sleep(1)
def func_ex():
sleep(2)
raise Exception("Blah")
x = [Thread(target=func, args=("T1",)), Thread(target=func, args=("T2",)), Thread(target=func_ex, args=())]
print "Starting"
for t in x:
t.start()
print "Joining"
for t in x:
t.join()
print "End"
「終了」の前に、スレッドを繰り返し処理し、失敗したものがないかどうかを確認してから、スクリプトを続行できるかどうか、またはこの時点で終了する必要があるかどうかを判断します。
例外をインターセプトしたり、他のスレッドを停止したりする必要はありません。失敗したスレッドがないかどうかを最後に知る必要があります。
スレッドに対するjoin()
呼び出しがスレッドのスタックを返すまでに、スレッドのスタックは巻き戻され、例外に関するすべての情報が失われています。したがって、残念ながら、例外を登録するための独自のメカニズムを提供する必要があります。いくつかのテクニックについて説明します ここ 。
例外を処理する必要がない状況での簡単な手法は、グローバルリストを使用して、それに関連情報を追加することです。コードは次のようになります。
#!/usr/bin/python
from time import sleep
from threading import Thread, current_thread #needed to get thread name or whatever identifying info you need
threadErrors = [] #global list
def func(a):
for i in range(0,5):
print a
sleep(1)
def func_ex():
global threadErrors #if you intend to change a global variable from within a different scope it has to be declared
try:
sleep(2)
raise Exception("Blah")
except Exception, e:
threadErrors.append([repr(e), current_thread.name]) #append a list of info
raise #re-raise the exception or use sys.exit(1) to let the thread die and free resources
x = [Thread(target=func, args=("T1",)), Thread(target=func, args=("T2",)), Thread(target=func_ex, args=())]
print "Starting"
for t in x:
t.start()
print "Joining"
for t in x:
t.join()
if len(threadErrors) > 0: #check if there are any errors
for e in threadErrors:
print(threadErrors[e][0]+' occurred in thread: '+threadErrors[e][1])
#do whatever with each error info
else:
#there are no errors so do normal clean-up stuff
#do clean-up that should happen in either case here
print "End"
注:グローバル変数は一般的に貧弱な手法と見なされますが、しかしスレッド間で通信するための単純なメカニズムです。一方のスレッドがこのルートで情報を送信している場合、もう一方のスレッドがそれを探している必要があることを覚えておく必要があります。