web-dev-qa-db-ja.com

スレッドにタイムアウトを設定するにはどうすればよいですか?

threading.Threadを使用してコードをマルチスレッド化しています。少なくとも1つのスレッドがX秒以内に作業を完了しなかった場合、Timeout exceptionをキャッチしたいと思います。私はここでそれに対処する方法を説明するいくつかの答えを見つけましたが、私はWindowsプラットフォームを使用しているのに対し、それらのほとんどはUNIX互換でした。

例のコード:

from threading import Thread
from time import sleep

def never_stop():
    while 1 > 0:
        print 'a'
        sleep(5)
        print 'b'
    return

t1 = Thread(target=never_stop)
t1.start()
t2 = Thread(target=never_stop)
t2.start()
t3 = Thread(target=never_stop)
t3.start()
t1.join(2)
t2.join(2)
t3.join(2)

joinメソッドでタイムアウトを設定しようとしましたが、役に立ちませんでした。

何か案は?

6
Dan

ドキュメント から:

timeout引数が存在し、Noneが存在しない場合、秒単位(またはその端数)で操作のタイムアウトを指定する浮動小数点数である必要があります。 join()は常にNoneを返すため、isAlive()の後にjoin()を呼び出して、タイムアウトが発生したかどうかを判断する必要があります。スレッドがまだ生きている場合は、 join()呼び出しがタイムアウトしました。

5
yael

最良の方法は、スレッドがそれ自体を閉じるようにすることです(開いているファイルまたは子スレッドを閉じることができるように、スレッドを「強制終了」しないでください)。
joinメソッドは、スレッドが終了するまで待機するだけで、スレッドを強制的に閉じることはありません。
never_stopメソッドを変更して時間を確認し、時間が経過したときにreturnまたはraiseXの制限を超えた場合に変更することをお勧めします。

def never_stop():
    time_started = time.time()
    X = 2
    while True:
        if time.time() > time_started + X:
            return  # or raise TimeoutException()
        print 'a' # do whatever you need to do

このようにして、スレッドはX秒後に終了します。スレッドを作成するときに、引数としてXを渡すこともできます。

def never_end(X):
    # rest stays the same, except for the X = 2


t1 = threading.Thread(target=never_stop, args=(2,))

argsはタプルであり、その内容は引数としてtarget関数に渡されます。

2
then0rTh