如何从其中一个线程退出整个Python应用程序? sys.exit()只终止调用它的线程,所以没有帮助。
我不想使用os.kill()解决方案,因为这不是很干净。
答案 0 :(得分:48)
如果除了主要线程之外的所有线程都是守护进程,最好的方法通常是thread.interrupt_main() - 任何线程都可以使用它来在主线程中引发KeyboardInterrupt
,这通常可以合理地导致从主线程中清除退出(包括调用主线程中的终结器等)。
当然,如果这会导致某些非守护程序线程保持整个进程存活,那么您需要按照Mark推荐的那样跟进os._exit
- 但我认为这是最后的手段(有点像a kill -9
;-)因为它非常粗暴地终止了事情(终结器未运行,包括try/finally
块,with
块,atexit
函数等。
答案 1 :(得分:42)
简短回答:使用os._exit
。
以答案为例:
我从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()
如果你将sys.exit(1)
注释掉,那么在第三个线程打印出来之后脚本就会死掉。如果您使用sys.exit(1)
并注释掉os._exit(1)
,则第三个帖子不打印(done)
,程序将运行所有七个帖子。
os._exit
“通常只应在fork()之后的子进程中使用” - 并且一个单独的线程足够接近你的目的。另请注意,在该手册页中os._exit
后面列出了几个枚举值,您应该更喜欢这些值作为os._exit
的参数,而不是像上面示例中使用的简单数字。
答案 2 :(得分:18)
在某些情况下使用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')
相关问题:
答案 3 :(得分:1)
退出整个程序的最简单方法是,我们应该使用进程ID(pid)终止程序。
import os
import psutil
current_system_pid = os.getpid()
ThisSystem = psutil.Process(current_system_pid)
ThisSystem.terminate()
要安装psutl:-“ pip install psutil”