【发布时间】:2010-12-02 03:48:40
【问题描述】:
如何从其中一个线程中退出整个 Python 应用程序? sys.exit() 只会终止调用它的线程,所以没有任何帮助。
我不想使用os.kill() 解决方案,因为这不是很干净。
【问题讨论】:
标签: python multithreading
如何从其中一个线程中退出整个 Python 应用程序? sys.exit() 只会终止调用它的线程,所以没有任何帮助。
我不想使用os.kill() 解决方案,因为这不是很干净。
【问题讨论】:
标签: python multithreading
简答:使用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 的参数,而不是像我在上面的示例中使用的简单数字。
【讨论】:
如果除主线程之外的所有线程都是守护进程,最好的方法通常是thread.interrupt_main()——任何线程都可以使用它在主线程中引发KeyboardInterrupt,这通常可以合理地从主线程退出主线程(包括被调用的主线程中的终结器等)。
当然,如果这导致某些非守护线程保持整个进程处于活动状态,您需要按照 Mark 的建议跟进 os._exit ——但我认为这是最后的手段(有点像 @ 987654324@;-) 因为它非常粗暴地终止事物(终结器未运行,包括 try/finally 块、with 块、atexit 函数等)。
【讨论】:
在某些情况下使用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')
相关问题:
【讨论】:
AttributeError: module 'signal' has no attribute 'SIGUSR1'
退出整个程序最简单的方法是,我们应该使用进程ID(pid)终止程序。
import os
import psutil
current_system_pid = os.getpid()
ThisSystem = psutil.Process(current_system_pid)
ThisSystem.terminate()
要安装 psutl:- “pip install psutil”
【讨论】:
os.kill(os.getpid(), signal.SIGTERM)