簡體   English   中英

如何中斷/停止/結束掛起的多線程python程序

[英]How to Interrupt/Stop/End a hanging multi-threaded python program

我有一個實現以下線程的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))

如果要在進程退出時強制所有線程退出,則可以在創建線程之前將線程的“守護程序”標志設置為True。

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

我用C做過一次。基本上,我有一個主要過程來啟動其他進程並跟蹤它們,即。 存儲PID並等待返回代碼。 如果您在進程中有錯誤,代碼將指示錯誤,然后您可以停止所有其他進程。 希望這可以幫助

編輯:

抱歉,我可能忘記了您使用的線程。 但我認為它仍然適用。 您可以包裝或修改線程以獲取返回值,也可以使用多線程池庫。

如何從python中的線程獲取返回值?

Python線程退出代碼

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM