如何中断/停止/结束挂起的多线程python程序

时间:2013-05-22 00:14:26

标签: python multithreading interrupt hung

我有一个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...

程序然后挂起或继续打印活动线程。但是,由于exit标志设置为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))

2 个答案:

答案 0 :(得分:2)

如果要在进程退出时强制退出所有线程,可以在创建线程之前将线程的“守护进程”标志设置为True。

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

答案 1 :(得分:0)

我在C中做过一次。基本上我有一个主要的过程,开始其他的并保持它们的轨迹,即。存储PID并等待返回码。如果进程中有错误,代码将指示,然后您可以停止其他所有进程。希望这有帮助

编辑:

抱歉,我可以忘记你的回答是你在使用线程。但我认为它仍然适用。您可以包装或修改线程以获取返回值,也可以使用多线程池库。

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

Python thread exit code