如何从Python线程退出整个应用程序?


73

如何从其线程之一退出整个Python应用程序?sys.exit()仅终止调用它的线程,所以没有帮助。

我不想使用os.kill()解决方案,因为这不是很干净。

Answers:


60

如果除主线程之外的所有线程都是守护进程,则最佳方法通常是thread.interrupt_main()-任何线程都可以使用它KeyboardInterrupt在主线程中引发a ,这通常会导致从主线程中合理地干净退出(包括主线程中的终结器被调用等)。

当然,如果这导致某些非守护进程线程使整个过程保持活动状态,则需要os._exit按照Mark的建议进行后续操作-但我认为这是最后的手段(有点像kill -9;-),因为它终止了事情非常残酷(finalizer不能运行,包括try/finally块,with块,atexit函数等)。


63

简短答案:使用 os._exit

示例的长答案:

我从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()

如果您继续sys.exit(1)注释掉,该脚本将在第三个线程打印完后消失。如果您使用sys.exit(1)并注释掉os._exit(1),则不会打印第三个线程(done),并通过所有七个线程的程序运行。

os._exit“通常只应在fork()之后在子进程中使用” –并且一个单独的线程与该线程足够接近以达到您的目的。还要注意,os._exit在该手册页的后面列出了几个枚举值,您应该更喜欢使用这些枚举值作为参数,os._exit而不是像上面示例中那样使用简单数字。


1
在Docker容器中运行时,这特别好用。Docker容器中的问题是我们无法杀死pid1。使用os._exit(1)可以工作。
ajaali

21

thread.interrupt_main()在某些情况下使用可能无济于事。KeyboardInterrupts通常在命令行应用程序中用于退出当前命令或清理输入行。

此外,os._exit如果不运行finally代码中的任何块,将立即终止该进程,这可能很危险(例如,文件和连接将不会关闭)。

我发现的解决方案是在引发自定义异常的主线程中注册信号处理程序。使用后台线程触发信号。

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')

相关问题:


2
这在Windows上不起作用AttributeError: module 'signal' has no attribute 'SIGUSR1'
pbn

Windows是否有替代方法?
MasayoMusic

1

退出整个程序的最简单方法是,我们应该使用进程ID(pid)终止程序。

import os
import psutil

current_system_pid = os.getpid()

ThisSystem = psutil.Process(current_system_pid)
ThisSystem.terminate()

要安装psutl:-“ pip install psutil”

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.