次のようなスレッドを実装する python プログラムがあります。
class Mythread(threading.Thread):
def __init__(self, name, q):
threading.Thread.__init__(self)
self.name = name
self.q = q
def run(self):
print "Starting %s..." % (self.name)
while True:
## Get data from queue
data = self.q.get()
## do_some_processing with data ###
process_data(data)
## Mark Queue item as done
self.q.task_done()
print "Exiting %s..." % (self.name)
def call_threaded_program():
##Setup the threads. Define threads,queue,locks
threads = []
q = Queue.Queue()
thread_count = n #some number
data_list = [] #some data list containing data
##Create Threads
for thread_id in range(1, thread_count+1):
thread_name = "Thread-" + str(thread_id)
thread = Mythread(thread_name,q)
thread.daemon = True
thread.start()
##Fill data in Queue
for data_item in data_list:
q.put(data_item)
try:
##Wait for queue to be exhausted and then exit main program
q.join()
except (KeyboardInterrupt, SystemExit) as e:
print "Interrupt Issued. Exiting Program with error state: %s"%(str(e))
exit(1)
call_threaded_program() が別のプログラムから呼び出されています。
通常の状況でコードが機能しています。ただし、いずれかのスレッドでエラー/例外が発生した場合、プログラムは停止します (キューの結合が無限にブロックされるため)。このプログラムを終了できる唯一の方法は、端末自体を閉じることです。
スレッドが抜けたときにこのプログラムを終了させる最善の方法は何ですか? これを行うクリーンな(実際には私は何らかの方法を取る)方法はありますか?この質問が何度も出されていることは知っていますが、説得力のある答えを見つけることができません。助けていただければ幸いです。
編集:キューの結合を削除しようとしましたが、Python でスレッドを強制終了する方法はありますか? で 提案されているように、グローバル終了フラグを使用しました。 しかし、今の行動はとても奇妙で、何が起こっているのか理解できません。
import threading
import Queue
import time
exit_flag = False
class Mythread (threading.Thread):
def __init__(self,name,q):
threading.Thread.__init__(self)
self.name = name
self.q = q
def run(self):
try:
# Start Thread
print "Starting %s...."%(self.name)
# Do Some Processing
while not exit_flag:
data = self.q.get()
print "%s processing %s"%(self.name,str(data))
self.q.task_done()
# Exit thread
print "Exiting %s..."%(self.name)
except Exception as e:
print "Exiting %s due to Error: %s"%(self.name,str(e))
def main():
global exit_flag
##Setup the threads. Define threads,queue,locks
threads = []
q = Queue.Queue()
thread_count = 20
data_list = range(1,50)
##Create Threads
for thread_id in range(1,thread_count+1):
thread_name = "Thread-" + str(thread_id)
thread = Mythread(thread_name,q)
thread.daemon = True
threads.append(thread)
thread.start()
##Fill data in Queue
for data_item in data_list:
q.put(data_item)
try:
##Wait for queue to be exhausted and then exit main program
while not q.empty():
pass
# Stop the threads
exit_flag = True
# Wait for threads to finish
print "Waiting for threads to finish..."
while threading.activeCount() > 1:
print "Active Threads:",threading.activeCount()
time.sleep(1)
pass
print "Finished Successfully"
except (KeyboardInterrupt, SystemExit) as e:
print "Interrupt Issued. Exiting Program with error state: %s"%(str(e))
if __name__ == '__main__':
main()
プログラムの出力は次のとおりです。
#Threads get started correctly
#The output also is getting processed but then towards the end, All i see are
Active Threads: 16
Active Threads: 16
Active Threads: 16...
その後、プログラムはハングするか、アクティブなスレッドの出力を続けます。ただし、終了フラグが True に設定されているため、スレッドの run メソッドは実行されていません。したがって、これらのスレッドがどのように維持されているか、または何が起こっているかについてはわかりません。
編集:問題が見つかりました。上記のコードでは、スレッドの get メソッドがブロックされていたため、終了できませんでした。代わりに、タイムアウト付きの get メソッドを使用するとうまくいきました。以下で変更した run メソッドだけのコードがあります
def run(self):
try:
#Start Thread
printing "Starting %s..."%(self.name)
#Do Some processing
while not exit_flag:
try:
data = self.q.get(True,self.timeout)
print "%s processing %s"%(self.name,str(data))
self.q.task_done()
except:
print "Queue Empty or Timeout Occurred. Try Again for %s"%(self.name)
# Exit thread
print "Exiting %s..."%(self.name)
except Exception as e:
print "Exiting %s due to Error: %s"%(self.name,str(e))