对于想了解终止多线程python程序的读者,本文将是一篇不可错过的文章,我们将详细介绍python停止多线程,并且为您提供关于Linux下后台运行和终止python程序常用命令、Python中用Ctr
对于想了解终止多线程python程序的读者,本文将是一篇不可错过的文章,我们将详细介绍python停止多线程,并且为您提供关于Linux下后台运行和终止python程序常用命令、Python 中用 Ctrl+C 终止多线程程序的问题解决、Python中用Ctrl+C终止多线程程序的问题解决、Python基础一(认识Python、搭建编程环境、第一个Python程序)的有价值信息。
本文目录一览:- 终止多线程python程序(python停止多线程)
- Linux下后台运行和终止python程序常用命令
- Python 中用 Ctrl+C 终止多线程程序的问题解决
- Python中用Ctrl+C终止多线程程序的问题解决
- Python基础一(认识Python、搭建编程环境、第一个Python程序)
终止多线程python程序(python停止多线程)
如何使多线程python程序响应Ctrl + C键事件?
编辑: 代码是这样的:
import threadingcurrent = 0class MyThread(threading.Thread): def __init__(self, total): threading.Thread.__init__(self) self.total = total def stop(self): self._Thread__stop() def run(self): global current while current<self.total: lock = threading.Lock() lock.acquire() current+=1 lock.release() print currentif __name__==''__main__'': threads = [] thread_count = 10 total = 10000 for i in range(0, thread_count): t = MyThread(total) t.setDaemon(True) threads.append(t) for i in range(0, thread_count): threads[i].start()
我试图在所有线程上删除join(),但仍然无法正常工作。是否因为每个线程的run()过程中的锁段?
编辑: 上面的代码应该可以工作,但是当当前变量在5,000-6,000范围内并遍历以下错误时,它总是会中断
Exception in thread Thread-4 (most likely raised during interpreter shutdown):Traceback (most recent call last): File "/usr/lib/python2.5/threading.py", line 486, in __bootstrap_inner File "test.py", line 20, in run<type ''exceptions.TypeError''>: unsupported operand type(s) for +=: ''NoneType'' and ''int''Exception in thread Thread-2 (most likely raised during interpreter shutdown):Traceback (most recent call last): File "/usr/lib/python2.5/threading.py", line 486, in __bootstrap_inner File "test.py", line 22, in run
答案1
小编典典在启动主线程之前,将除主线程之外的每个线程都设为守护进程(t.daemon =True
在2.6或更高版本中,t.setDaemon(True)
在2.6或更低版本中,针对每个线程对象t
)。这样,当主线程收到KeyboardInterrupt时,如果它没有捕获到或捕获到它,但是无论如何都决定终止,则整个过程将终止。请参阅文档。
编辑 :刚刚看过OP的代码(最初未发布)和声称“它不起作用”,看来我必须添加…:
当然,如果你希望你的主线程保持响应(例如,为了控制-C),不泥潭成阻塞调用,如join
荷兰国际集团另一个线程-尤其是没有完全 无用的
阻塞调用,如join
荷兰国际集团 守护 线程。例如,仅更改当前线程在主线程中的最终循环(完全无损):
for i in range(0, thread_count): threads[i].join()
像这样更明智:
while threading.active_count() > 0: time.sleep(0.1)
如果您的main没有比将所有线程自己终止或接收control-C(或其他信号)更好的事情了。
当然,如果您不想让线程突然终止(如守护线程可能),还有许多其他可用的模式-除非 它们 也被永久地陷入无条件阻塞的调用,死锁等;-) 。
Linux下后台运行和终止python程序常用命令
后台运行python程序
- 后台运行程序
运行test.py,标准输出(运行记录)保存在log.txt中
nohup python -u test.py > log.txt 2>&1 &
nohup是no hang up,& 是后台运行,两者结合可以在用户退出时,保持后台运行
-u 是不启用缓存,不然的话print重定向写入文件的过程会有缓存,log.txt文件不会实时更新
2>&1 错误重定向到标准输出
终止程序运行
- 观察GPU使用情况
在实验的过程中,我们可能会因为代码bug等各种原因,希望提前停止在后台运行的程序。但是此时可能你已经记不清后台运行的多个程序中,哪一个是我们想要停止的程序。此时可以先通过观察GPU的使用情况命令,获取正在GPU上运行的程序的pid。
watch -n 1 nvidia-smi
- 根据pid查看对应的程序
在或许到后台运行的程序的pid集合后,我们可以通过以下命令查看每个pid对应的程序,运行后会输出我们运行程序使用的命令以及命令行参数,从而找到需要提前终止的程序。
ps -ef|grep 16923
- 终止程序
假设pid为16923的程序就是我们希望提前终止的程序,那么我们使用以下命令提前终止程序的运行。
kill -9 16923
Python 中用 Ctrl+C 终止多线程程序的问题解决
花了一天时间用python为服务写了个压力测试。很简单,多线程向服务器发请求。但写完之后发现如果中途想停下来,按Ctrl+C达不到效果,自然想到要用信号处理函数捕捉信号,使线程都停下来,问题解决的方法请往下看:
#!/bin/env python
# -*- coding: utf-8 -*-
#filename: peartest.py
import threading, signal
is_exit = False
def doStress(i, cc):
global is_exit
idx = i
while not is_exit:
if (idx < 10000000):
print "thread[%d]: idx=%d"%(i, idx)
idx = idx + cc
else:
break
print "thread[%d] complete."%i
def handler(signum, frame):
global is_exit
is_exit = True
print "receive a signal %d, is_exit = %d"%(signum, is_exit)
if __name__ == "__main__":
signal.signal(signal.SIGINT, handler)
signal.signal(signal.SIGTERM, handler)
cc = 5
for i in range(cc):
t = threading.Thread(target=doStress, args=(i,cc))
t.start()
上面是一个模拟程序,并不真正向服务发送请求,而代之以在一千万以内,每个线程每隔并发数个(cc个)打印一个整数。很明显,当所有线程都完成自己的任务后,进程会正常退出。但如果我们中途想退出(试想一个压力测试程序,在中途已经发现了问题,需要停止测试),该肿么办?你当然可以用ps查找到进程号,然后kill -9杀掉,但这样太繁琐了,捕捉Ctrl+C是最自然的想法。上面示例程序中已经捕捉了这个信号,并修改全局变量is_exit,线程中会检测这个变量,及时退出。
但事实上这个程序并不work,当你按下Ctrl+C时,程序照常运行,并无任何响应。网上搜了一些资料,明白是python的子线程如果不是daemon的话,主线程是不能响应任何中断的。但设为daemon后主线程会随之退出,接着整个进程很快就退出了,所以还需要在主线程中检测各个子线程的状态,直到所有子线程退出后自己才退出,因此上例29行之后的代码可以修改为:
threads=[]
for i in range(cc):
t = threading.Thread(target=doStress, args=(i, cc))
t.setDaemon(True)
threads.append(t)
t.start()
for i in range(cc):
threads[i].join()
重新试一下,问题依然没有解决,进程还是没有响应Ctrl+C,这是因为join()函数同样会waiting在一个锁上,使主线程无法捕获信号。因此继续修改,调用线程的isAlive()函数判断线程是否完成:
while 1:
alive = False
for i in range(cc):
alive = alive or threads[i].isAlive()
if not alive:
break
这样修改后,程序完全按照预想运行了:可以顺利的打印每个线程应该打印的所有数字,也可以中途用Ctrl+C终结整个进程。完整的代码如下:
#!/bin/env python
# -*- coding: utf-8 -*-
#filename: peartest.py
import threading, signal
is_exit = False
def doStress(i, cc):
global is_exit
idx = i
while not is_exit:
if (idx < 10000000):
print "thread[%d]: idx=%d"%(i, idx)
idx = idx + cc
else:
break
if is_exit:
print "receive a signal to exit, thread[%d] stop."%i
else:
print "thread[%d] complete."%i
def handler(signum, frame):
global is_exit
is_exit = True
print "receive a signal %d, is_exit = %d"%(signum, is_exit)
if __name__ == "__main__":
signal.signal(signal.SIGINT, handler)
signal.signal(signal.SIGTERM, handler)
cc = 5
threads = []
for i in range(cc):
t = threading.Thread(target=doStress, args=(i,cc))
t.setDaemon(True)
threads.append(t)
t.start()
while 1:
alive = False
for i in range(cc):
alive = alive or threads[i].isAlive()
if not alive:
break
其实,如果用python写一个服务,也需要这样,因为负责服务的那个线程是永远在那里接收请求的,不会退出,而如果你想用Ctrl+C杀死整个服务,跟上面的压力测试程序是一个道理。
总结一下,python多线程中要响应Ctrl+C的信号以杀死整个进程,需要:
1.把所有子线程设为Daemon;
2.使用isAlive()函数判断所有子线程是否完成,而不是在主线程中用join()函数等待完成;
3.写一个响应Ctrl+C信号的函数,修改全局变量,使得各子线程能够检测到,并正常退出。
Python中用Ctrl+C终止多线程程序的问题解决
#!/bin/env python
# -*- coding: utf-8 -*-
#filename: peartest.py
import threading, signal
is_exit = False
def doStress(i, cc):
global is_exit
idx = i
while not is_exit:
if (idx print "thread[%d]: idx=%d"%(i, idx)
idx = idx + cc
else:
break
print "thread[%d] complete."%i
def handler(signum, frame):
global is_exit
is_exit = True
print "receive a signal %d, is_exit = %d"%(signum, is_exit)
if __name__ == "__main__":
signal.signal(signal.SIGINT, handler)
signal.signal(signal.SIGTERM, handler)
cc = 5
for i in range(cc):
t = threading.Thread(target=doStress, args=(i,cc))
t.start()
上面是一个模拟程序,并不真正向服务发送请求,而代之以在一千万以内,每个线程每隔并发数个(cc个)打印一个整数。很明显,当所有线程都完成自己的任务后,进程会正常退出。但如果我们中途想退出(试想一个压力测试程序,在中途已经发现了问题,需要停止测试),该肿么办?你当然可以用ps查找到进程号,然后kill -9杀掉,但这样太繁琐了,捕捉Ctrl+C是最自然的想法。上面示例程序中已经捕捉了这个信号,并修改全局变量is_exit,线程中会检测这个变量,及时退出。
但事实上这个程序并不work,当你按下Ctrl+C时,程序照常运行,并无任何响应。网上搜了一些资料,明白是python的子线程如果不是daemon的话,主线程是不能响应任何中断的。但设为daemon后主线程会随之退出,接着整个进程很快就退出了,所以还需要在主线程中检测各个子线程的状态,直到所有子线程退出后自己才退出,因此上例29行之后的代码可以修改为:
threads=[]
for i in range(cc):
t = threading.Thread(target=doStress, args=(i, cc))
t.setDaemon(True)
threads.append(t)
t.start()
for i in range(cc):
threads[i].join()
重新试一下,问题依然没有解决,进程还是没有响应Ctrl+C,这是因为join()函数同样会waiting在一个锁上,使主线程无法捕获信号。因此继续修改,调用线程的isAlive()函数判断线程是否完成:
while 1:
alive = False
for i in range(cc):
alive = alive or threads[i].isAlive()
if not alive:
break
这样修改后,程序完全按照预想运行了:可以顺利的打印每个线程应该打印的所有数字,也可以中途用Ctrl+C终结整个进程。完整的代码如下:
#!/bin/env python
# -*- coding: utf-8 -*-
#filename: peartest.py
import threading, signal
is_exit = False
def doStress(i, cc):
global is_exit
idx = i
while not is_exit:
if (idx print "thread[%d]: idx=%d"%(i, idx)
idx = idx + cc
else:
break
if is_exit:
print "receive a signal to exit, thread[%d] stop."%i
else:
print "thread[%d] complete."%i
def handler(signum, frame):
global is_exit
is_exit = True
print "receive a signal %d, is_exit = %d"%(signum, is_exit)
if __name__ == "__main__":
signal.signal(signal.SIGINT, handler)
signal.signal(signal.SIGTERM, handler)
cc = 5
threads = []
for i in range(cc):
t = threading.Thread(target=doStress, args=(i,cc))
t.setDaemon(True)
threads.append(t)
t.start()
while 1:
alive = False
for i in range(cc):
alive = alive or threads[i].isAlive()
if not alive:
break
其实,如果用python写一个服务,也需要这样,因为负责服务的那个线程是永远在那里接收请求的,不会退出,而如果你想用Ctrl+C杀死整个服务,跟上面的压力测试程序是一个道理。总结一下,python多线程中要响应Ctrl+C的信号以杀死整个进程,需要:
1.把所有子线程设为Daemon;
2.使用isAlive()函数判断所有子线程是否完成,而不是在主线程中用join()函数等待完成;
3.写一个响应Ctrl+C信号的函数,修改全局变量,使得各子线程能够检测到,并正常退出。