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

lin*_*r03 58 python multithreading

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

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

Ale*_*lli 52

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

当然,如果这导致一些非守护进程线程保持整个进程存活,你需要os._exit按照马克推荐的那样进行跟进- 但我认为这是最后的手段(有点像kill -9;-)因为它终止了事情相当粗暴(终结者不运行,包括try/finally块,with块,atexit功能等).

  • 看来这实际上“不是”最好的方法,因为它没有添加到 Python 3 中的“线程”中。 (2认同)

Mar*_*off 49

简答:使用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()
Run Code Online (Sandbox Code Playgroud)

如果你继续sys.exit(1)注释,脚本将在第三个线程打印出来后死亡.如果你使用sys.exit(1)和注释掉os._exit(1),第三个线程并不能打印(done),程序通过所有七个线程运行.

os._exit"通常只应在fork()之后的子进程中使用" - 并且一个单独的线程足够接近你的目的.另请注意,os._exit在该手册页中紧接着列出了几个枚举值,您应该更喜欢那些作为参数,os._exit而不是像我在上面的示例中使用的简单数字.

  • 当在 Docker 容器中运行时,这尤其有效。docker 容器中的问题是我们无法杀死 pid 1。使用 os._exit(1) 有效。 (2认同)

Nag*_*i45 19

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')
Run Code Online (Sandbox Code Playgroud)

相关问题:

  • 这不适用于 windows `AttributeError: module 'signal' has no attribute 'SIGUSR1'` (3认同)
  • 对于 Windows 有替代方案吗? (2认同)

小智 5

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

import os
import psutil

current_system_pid = os.getpid()

ThisSystem = psutil.Process(current_system_pid)
ThisSystem.terminate()
Run Code Online (Sandbox Code Playgroud)

要安装 psutl:-“pip install psutil”

  • 实际上,有一种更简单的方法,无需引入任何依赖项:`os.kill(os.getpid(), signal.SIGTERM)` (3认同)