如何从Python线程中退出整个应用程序?
我该如何从我的Python应用程序中的一个线程退出整个应用呢?调用sys.exit()
只会结束它被调用的那个线程,这样对我没什么帮助。
我不想使用os.kill()
这种方法,因为这看起来不太干净。
7 个回答
使用 thread.interrupt_main()
在某些情况下可能没什么用。KeyboardInterrupt
通常是在命令行应用中用来退出当前命令或者清理输入行的。
另外,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')
相关问题:
简单来说:使用 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
的参数,而不是像我在上面的例子中用的简单数字。
如果你除了主线程之外的所有线程都是守护线程,那么通常最好的办法是使用 thread.interrupt_main()。任何线程都可以用这个方法在主线程中引发一个 KeyboardInterrupt
,这样通常可以让主线程比较干净地退出(包括主线程中的一些清理工作会被调用等)。
当然,如果这样做导致某个非守护线程让整个程序一直运行下去,那么你需要按照Mark的建议使用 os._exit
。但我认为这应该是最后的手段(有点像 kill -9
;-)因为这样会很粗暴地结束程序(不会执行清理工作,包括 try/finally
块、 with
块、 atexit
函数等)。