How to exit the entire application from a Python thread?

后端 未结 4 1377
醉酒成梦
醉酒成梦 2020-11-29 00:53

How can I exit my entire Python application from one of its threads? sys.exit() only terminates the thread in which it is called, so that is no help.

I w

相关标签:
4条回答
  • 2020-11-29 01:00

    Short answer: use os._exit.

    Long answer with example:

    I yanked and slightly modified a simple threading example from a tutorial on DevShed:

    import threading, sys, os
    
    theVar = 1
    
    class MyThread ( threading.Thread ):
    
       def run ( self ):
    
          global theVar
          print 'This is thread ' + str ( theVar ) + ' speaking.'
          print 'Hello and good bye.'
          theVar = theVar + 1
          if theVar == 4:
              #sys.exit(1)
              os._exit(1)
          print '(done)'
    
    for x in xrange ( 7 ):
       MyThread().start()
    

    If you keep sys.exit(1) commented out, the script will die after the third thread prints out. If you use sys.exit(1) and comment out os._exit(1), the third thread does not print (done), and the program runs through all seven threads.

    os._exit "should normally only be used in the child process after a fork()" -- and a separate thread is close enough to that for your purpose. Also note that there are several enumerated values listed right after os._exit in that manual page, and you should prefer those as arguments to os._exit instead of simple numbers like I used in the example above.

    0 讨论(0)
  • 2020-11-29 01:00

    Using thread.interrupt_main() may not help in some situation. KeyboardInterrupts are often used in command line applications to exit the current command or to clean the input line.

    In addition, os._exit will kill the process immediately without running any finally blocks in your code, which may be dangerous (files and connections will not be closed for example).

    The solution I've found is to register a signal handler in the main thread that raises a custom exception. Use the background thread to fire the signal.

    import signal
    import os
    import threading
    import time
    
    
    class ExitCommand(Exception):
        pass
    
    
    def signal_handler(signal, frame):
        raise ExitCommand()
    
    
    def thread_job():
        time.sleep(5)
        os.kill(os.getpid(), signal.SIGUSR1)
    
    
    signal.signal(signal.SIGUSR1, signal_handler)
    threading.Thread(target=thread_job).start()  # thread will fire in 5 seconds
    try:
        while True:
            user_input = raw_input('Blocked by raw_input loop ')
            # do something with 'user_input'
    except ExitCommand:
        pass
    finally:
        print('finally will still run')
    

    Related questions:

    • Why does sys.exit() not exit when called inside a thread in Python?
    • Python: How to quit CLI when stuck in blocking raw_input?
    0 讨论(0)
  • 2020-11-29 01:16

    If all your threads except the main ones are daemons, the best approach is generally thread.interrupt_main() -- any thread can use it to raise a KeyboardInterrupt in the main thread, which can normally lead to reasonably clean exit from the main thread (including finalizers in the main thread getting called, etc).

    Of course, if this results in some non-daemon thread keeping the whole process alive, you need to followup with os._exit as Mark recommends -- but I'd see that as the last resort (kind of like a kill -9;-) because it terminates things quite brusquely (finalizers not run, including try/finally blocks, with blocks, atexit functions, etc).

    0 讨论(0)
  • 2020-11-29 01:18

    The easiest way to exit the whole program is, we should terminate the program by using the process id (pid).

    import os
    import psutil
    
    current_system_pid = os.getpid()
    
    ThisSystem = psutil.Process(current_system_pid)
    ThisSystem.terminate()
    

    To install psutl:- "pip install psutil"

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