Cannot kill Python script with Ctrl-C

前端 未结 4 917
醉酒成梦
醉酒成梦 2020-11-27 10:56

I am testing Python threading with the following script:

import threading

class FirstThread (threading.Thread):
    def run (self):
        while True:
             


        
相关标签:
4条回答
  • 2020-11-27 11:24

    Ctrl+C terminates the main thread, but because your threads aren't in daemon mode, they keep running, and that keeps the process alive. We can make them daemons:

    f = FirstThread()
    f.daemon = True
    f.start()
    s = SecondThread()
    s.daemon = True
    s.start()
    

    But then there's another problem - once the main thread has started your threads, there's nothing else for it to do. So it exits, and the threads are destroyed instantly. So let's keep the main thread alive:

    import time
    while True:
        time.sleep(1)
    

    Now it will keep print 'first' and 'second' until you hit Ctrl+C.

    Edit: as commenters have pointed out, the daemon threads may not get a chance to clean up things like temporary files. If you need that, then catch the KeyboardInterrupt on the main thread and have it co-ordinate cleanup and shutdown. But in many cases, letting daemon threads die suddenly is probably good enough.

    0 讨论(0)
  • 2020-11-27 11:29

    I think it's best to call join() on your threads when you expect them to die. I've taken some liberty with your code to make the loops end (you can add whatever cleanup needs are required to there as well). The variable die is checked for truth on each pass and when it's True then the program exits.

    import threading
    import time
    
    class MyThread (threading.Thread):
        die = False
        def __init__(self, name):
            threading.Thread.__init__(self)
            self.name = name
    
        def run (self):
            while not self.die:
                time.sleep(1)
                print (self.name)
    
        def join(self):
            self.die = True
            super().join()
    
    if __name__ == '__main__':
        f = MyThread('first')
        f.start()
        s = MyThread('second')
        s.start()
        try:
            while True:
                time.sleep(2)
        except KeyboardInterrupt:
            f.join()
            s.join()
    
    0 讨论(0)
  • 2020-11-27 11:43

    An improved version of @Thomas K's answer:

    • Defining an assistant function is_any_thread_alive() according to this gist, which can terminates the main() automatically.

    Example codes:

    import threading
    
    def job1():
        ...
    
    def job2():
        ...
    
    def is_any_thread_alive(threads):
        return True in [t.is_alive() for t in threads]
    
    if __name__ == "__main__":
        ...
        t1 = threading.Thread(target=job1,daemon=True)
        t2 = threading.Thread(target=job2,daemon=True)
        t1.start()
        t2.start()
    
        while is_any_thread_alive([t1,t2]):
            time.sleep(0)
    
    0 讨论(0)
  • 2020-11-27 11:46

    KeyboardInterrupt and signals are only seen by the process (ie the main thread)... Have a look at Ctrl-c i.e. KeyboardInterrupt to kill threads in python

    0 讨论(0)
提交回复
热议问题