如何从其线程之一退出整个Python应用程序?sys.exit()
仅终止调用它的线程,所以没有帮助。
我不想使用os.kill()
解决方案,因为这不是很干净。
如何从其线程之一退出整个Python应用程序?sys.exit()
仅终止调用它的线程,所以没有帮助。
我不想使用os.kill()
解决方案,因为这不是很干净。
Answers:
如果除主线程之外的所有线程都是守护进程,则最佳方法通常是thread.interrupt_main()-任何线程都可以使用它KeyboardInterrupt
在主线程中引发a ,这通常会导致从主线程中合理地干净退出(包括主线程中的终结器被调用等)。
当然,如果这导致某些非守护进程线程使整个过程保持活动状态,则需要os._exit
按照Mark的建议进行后续操作-但我认为这是最后的手段(有点像kill -9
;-),因为它终止了事情非常残酷(finalizer不能运行,包括try/finally
块,with
块,atexit
函数等)。
简短答案:使用 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
s通常在命令行应用程序中用于退出当前命令或清理输入行。
此外,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')
相关问题:
AttributeError: module 'signal' has no attribute 'SIGUSR1'