Python2:守护进程线程在键盘中断时未被杀死
我正在编写一个简单的线程应用程序,我将线程设置为Python2:守护进程线程在键盘中断时未被杀死,python,multithreading,Python,Multithreading,我正在编写一个简单的线程应用程序,我将线程设置为守护进程,因为我希望我的程序在键盘中断时退出。这可以很好地使用python3获得预期的结果,但是python2.7似乎不尊重守护进程标志。下面是我的示例代码 if __name__ == '__main__': try: threads = [Thread(target=some_func, args=(arg1,arg2)) for _ in range(10)] for th in threads:
守护进程
,因为我希望我的程序在键盘中断时退出。这可以很好地使用python3
获得预期的结果,但是python2.7
似乎不尊重守护进程
标志。下面是我的示例代码
if __name__ == '__main__':
try:
threads = [Thread(target=some_func, args=(arg1,arg2)) for _ in range(10)]
for th in threads:
th.daemon=True
th.start()
for th in threads:
th.join()
except KeyboardInterrupt:
sys.exit('Ctrl-c issued by user .. Exiting')
当我在python3
上运行此代码,然后按ctrl-c
一段时间后,我的程序按预期退出,但当我在python2.7
上运行此代码,然后按ctrl-c
时,它永远不会退出,我必须从shell中终止进程
我是不是遗漏了什么?我还尝试设置threading.Event
,然后在键盘中断发生时清除该事件,但即使这样也不起作用
使用python3
如果我不join
mydaemon
线程,那么它们将在my程序完成后立即退出,如果我不将我的线程标记为daemon
并且不join
则程序将继续,只要我点击ctrl-c
它就会退出。但是这些都不适用于python2.7
编辑#1
我对它做了更多的研究,它看起来像是python2.7
无法捕捉KeyboardInterrupt
。这更奇怪,因为KeyboardInterrupt
工作正常,它是一个非线程程序,但是对于线程KeyboardInterrupt
不会被捕获,即使线程被标记为守护进程
所有这些都只发生在python2.7上,而python3
工作得很好。线程的方式。在较旧版本的Python中,join
可以默默地吞下信号,直到join
完成。这包括SIGINT aka键盘中断
作为一种解决方法,您可以尝试短时间睡眠
或加入
。如果您希望线程自行消亡,请确保清理:
while threads:
threads[-1].join(1) # allow KeyboardInterrup once per second
if not threads[-1].is_alive(): # reap dead Threads
threads.pop()
我的第一个想法是使用thread.join,但这似乎会阻止主进程(忽略KeyboardInterrupt),直到线程完成
多线程Python程序通常会忽略键盘中断生成的SIGINT,特别是当获取信号的线程正在等待或休眠时
我使用的是Python2.7,我的程序在使用时忽略SIGTERM信号
线程池执行器
经过一些调试后,我发现我的主线程在thread.join()上被阻塞,
它会保持中断直到呼叫返回
在较旧版本的Python中,Thread.join
的工作方式可以默默地吞下信号,直到join
完成。这包括SIGINT aka键盘中断
作为一种解决方法,您可以尝试短时间睡眠
或加入
。如果您希望线程自行消亡,请确保清理:
while threads:
threads[-1].join(1) # allow KeyboardInterrup once per second
if not threads[-1].is_alive(): # reap dead Threads
threads.pop()
我的第一个想法是使用thread.join,但这似乎会阻止主进程(忽略KeyboardInterrupt),直到线程完成
多线程Python程序通常会忽略键盘中断生成的SIGINT,特别是当获取信号的线程正在等待或休眠时
我使用的是Python2.7,我的程序在使用时忽略SIGTERM信号
线程池执行器
经过一些调试后,我发现我的主线程在thread.join()上被阻塞,
它会保持中断直到呼叫返回
感谢@mistermiagi的建议,我能够测试本文中提到的一些解决方案
请注意下面的解决方案仅适用于守护进程
线程,因为如果将连接
放在主程序上,非守护进程将始终阻止主程序,直到它完成其工作。如果您没有在非守护进程线程上放置一个join
,那么如果您的main已退出,并且这是预期的行为,那么它们将继续在后台运行
我遇到的问题是专门针对守护进程线程的。下面是解决方案
#1:不要在线程上放置联接,因为它会导致线程阻塞主进程。这是因为守护进程
线程在主程序退出后立即退出,因此当您没有加入时,您就没有在主程序中等待,这是时间。睡眠(1)
在内部而只是为了确保守护进程
线程继续执行,并且只要我点击ctrl-c
,main将退出,守护进程
线程也将退出
if __name__ == "__main__":
try:
threads = [threading.Thread(name='daemon', target=daemon)
for _ in range(8)]
for th in threads:
th.daemon = True
th.start()
while True:
time.sleep(1)
# signal.pause() # This worked fine for me on Linux, on Windows it doesn't work, not sure about Mac. I am not recommending this because of platform dependency.
except KeyboardInterrupt:
#2:如果要在线程上放置连接
,请使用超时,然后在循环检查期间将其保持在中,直到线程
处于活动状态。这样做的目的是继续检查threads
列表中的每个线程,直到它处于活动状态,然后等待1秒执行它。现在由于而
条件将为真
,直到线程
完成后实际收割;它将以1秒的时间小块阻塞主程序,一旦您点击ctrl-c
,守护进程线程
将不再处于活动状态,因此主程序退出
if __name__ == "__main__":
try:
threads = [threading.Thread(name='daemon', target=daemon)
for _ in range(8)]
for th in threads:
th.daemon = True
th.start()
for th in threads:
while th.isAlive():
th.join(1)
except KeyboardInterrupt:
print('ctrl-c')
感谢@mistermiagi的建议,我能够测试本文中提到的一些解决方案
请注意下面的解决方案仅适用于守护进程
线程,因为如果将连接
放在主程序上,非守护进程将始终阻止主程序,直到它完成其工作。如果您没有在非守护进程线程上放置一个join
,那么如果您的main已退出,并且这是预期的行为,那么它们将继续在后台运行
我遇到的问题是专门针对守护进程线程的。下面是解决方案