2016-04-06 6 views
0

スレッドでPythonキューを使用しています。私は、ワーカーがクラッシュしたときにスクリプトがハングして終了させないことに気付きました。以下はその例です:ワーカーがクラッシュしたときに待ち行列がハングする

from Queue import Queue 
from threading import Thread 

num_worker_threads = 2 

def worker(): 
     while True: 
       item = q.get() 
       1/item 
       q.task_done() 
q = Queue() 
for i in range(num_worker_threads): 
     t = Thread(target=worker) 
     t.daemon = True 
     t.start() 

q.put(0) 
q.join() 

答えて

1

例外でジョブをラップすることでこれを解決しました。私は、労働者がクラッシュすると、スクリプトが終了すると思っていたでしょう。これはそうではありません。 q.task_done()は呼び出されないので、q.join()でハングします。

ソリューション:RSYによって

from Queue import Queue 
from threading import Thread 

num_worker_threads = 2 

def worker(): 
     while True: 
       item = q.get() 
       try: 
         1/item 
       except Exception as e: 
         print e 
       finally: 
         q.task_done() 
q = Queue() 
for i in range(num_worker_threads): 
     t = Thread(target=worker) 
     t.daemon = True 
     t.start() 

q.put(0) 
q.join() 

追加提案。

0

Queueの要素を継続的に取得しようとしているwhile Trueをスレッド内でq.get()と呼びますが、キューに項目がない可能性があります。実際にはキューには何もないので、Empty例外がスローされます。

ループはwhile not q.empty():である必要があります。または、Queue.Emptyの例外をキャッチする必要があります。

+0

ワーカースレッドがデーモンの場合、メインスレッドが終了すると終了します。メインスレッドは、キューを含むすべてのタスクが完了したときに終了しました。それは例外が発生したためにタスクが完了しなかったためにハングしていました。 – Mocking

1

さらに洗練されたアプローチは、代わりにfinallyブロックにtask_done()を入れることです。

from Queue import Queue 
from threading import Thread 

num_worker_threads = 2 

def worker(): 
     while True: 
       item = q.get() 
       try: 
         1/item 
       except Exception as e: 
         print e 
       finally: 
         q.task_done() 
q = Queue() 
for i in range(num_worker_threads): 
     t = Thread(target=worker) 
     t.daemon = True 
     t.start() 

q.put(0) 
q.join() 
関連する問題