2013-05-22 64 views
3

我有一個實現線程像這樣的Python程序:如何中斷/停止/結束懸掛多線程的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()是從不同的程序調用。

我的代碼在正常情況下工作。但是,如果在其中一個線程中發生錯誤/異常,程序就會卡住(因爲隊列連接無限阻塞)。我能夠退出該計劃的唯一方法是關閉終端本身。

線程退出時終止此程序的最佳方法是什麼?有沒有乾淨的(其實我會採取任何方式)這樣做?我知道這個問題已經被無數次地問過了,但我仍然無法找到令人信服的答案。我真的很感激任何幫助。

編輯: 我試着刪除隊列中的連接和使用的全球出口標誌爲Is there any way to kill a Thread in 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,所以線程的運行方法未被執行。所以我不知道如何保持這些線程或發生了什麼。

編輯: 我發現了這個問題。在上面的代碼中,線程的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)) 

回答

0

我在C.做到了一次基本上我有這樣開始了其他的人,並讓他們的軌道,即主要工序中的代碼。存儲PID並等待返回碼。如果您在某個流程中出現錯誤,代碼將會顯示,然後您可以停止其他所有流程。希望這有助於

編輯:

對不起,我可以在我的答案,你是使用線程都忘記了。但我認爲它仍然適用。您可以打包或修改線程以獲取返回值,也可以使用多線程池庫。

how to get the return value from a thread in python?

Python thread exit code

+0

您好,我試過包裝線程捕獲異常,並使用全球出口標誌停止線程。但現在的行爲很奇怪,這超出了我的理解。請參閱上面的編輯 – NRS

2

如果要強制所有線程退出時,進程退出,你在創建線程之前,可以設置線程的「守護進程」標誌設置爲True。

http://docs.python.org/2/library/threading.html#threading.Thread.daemon

+0

我已經爲該線程設置了「守護程序」標誌。請參閱上面的代碼。但那不是問題。問題是,主進程不會退出,因爲它正在等待隊列耗盡。然而,隊列永遠不會退出,因爲線程死了(因此沒有人使用隊列中的項目)。所以,這導致程序被卡住了。但我想我已經想出了這個問題(請參閱編輯) – NRS