问答文章1 问答文章501 问答文章1001 问答文章1501 问答文章2001 问答文章2501 问答文章3001 问答文章3501 问答文章4001 问答文章4501 问答文章5001 问答文章5501 问答文章6001 问答文章6501 问答文章7001 问答文章7501 问答文章8001 问答文章8501 问答文章9001 问答文章9501

python 多线程ctrl+c不起作用

发布网友 发布时间:2022-04-21 14:32

我来回答

2个回答

懂视网 时间:2022-05-11 02:43

代码如下:


#!/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信号的函数,修改全局变量,使得各子线程能够检测到,并正常退出。

热心网友 时间:2022-05-10 23:51

我这上不了百度网盘,没法下载,看不了你的代码。但是可以给你个解决思路,你可以写把进程号传出来,到时候外面有个程序来处理。ctrl C肯定是停不了的。
还有就是Python多线程涉及到线程安全,推荐你使用多进程。
nostmabole手打,望采纳。追问线程安全是什么意思

追答一段代码,同时几个线程同时使用,结果都是正确的,就叫线程安全。
举个例子吧
比如说,现在有一篮子苹果,有大有小,然后有一群人要来拿苹果了
在线程非安全情况下:
所有人一哄而上,变成了抢苹果了,因为大家都想要的苹果,会发生冲突的
在线程安全情况下:
把这一篮子苹果放到一个小屋里面,然后锁起来,然后每次只让一个人进去拿,等那个人拿完然后再让下一个人进去拿,这样保证了每个人都能拿到苹果,而且不会出现冲突。
在Java中 Vector:是线程安全的 ArrayList:不是线程安全的。涉及到数值改变的同步性问题。
Python中多线程去处理List如果不注意很容易出现线程不安全,结果不正确的情况。所以要注意,但是使用多进程就没有这样的问题。多进程使用Process类。具体的你用法自己百度吧。
最后再补充一句,由于线程锁这块,Python一直是个坑。多线程在多核CPU运行的时候效率反而下降了。所以 一般我都是用多进程替代 坑爹的多线程。由于篇幅有限,你可以自己百度一下 Python线程锁 去了解,我就不给你粘贴相关的内容了。

声明声明:本网页内容为用户发布,旨在传播知识,不代表本网认同其观点,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。E-MAIL:11247931@qq.com
八月中国最凉快的地方 八月份哪里最凉快,去哪旅游好?美丽的地方 乱字同韵字是什么意思 华硕笔记本电脑触摸板怎么开笔记本电脑触摸板怎么开启和关闭_百度知 ... 陕西职务侵占案立案准则 结婚后我的恋情维系了十年,怎么做到的? 玉米仁子饭产自哪里 中国期货交易所的交易品种有哪些? 历史要怎么读,有啥诀窍 高中历史诀窍 python中IDLE的Ctrl+j换行表示什么? python的一段代码在终端上可以运行,在sublime中ctrl+b就不能运行,是怎么回事? python 怎么让程序接受ctrl + c终止信号 Python快捷键“ctrl+Enter”有时无法使用? python如何使用ctrl+c来退出程序? python运行快捷键是什么 Python如何按住ctrl和一个英文键 有谁知道,怎么清洗羽绒服效果好? 微信进入qq邮箱每次都需要密码 如何判断一个QQ号是否已经注销了? 微信查看qq邮箱的邮件,却提示要输入qq密码,可以输吗?会不会被盗号? 微信QQ邮箱要我输入密码,是不是恶意邮件导致的? 微信里的一句“收到”,到底有多重要? 微信qq邮箱提醒点击邮件输入qq密码是微信官方统一的吗 收到的拼音 微信查看qq邮箱的邮件,却提示要输入qq密码,可以输吗?会不会被盗号? 微信查看qq邮箱的邮件,却提示要输入qq密码,可以输吗?会不会被盗号? 周传雄的《我难过》 歌词 歌词最后,我决定放弃,成全你和她的爱是什么歌 周传雄的《我难过》 歌词 python 如何将ctrl+a复制的内容print出来? python自带的shell编辑器,按ctrl+n之后在新弹出的页面写,不能正常使用,是什么情况? python 执行过程中停止,只有Ctrl+C后才会继续执行 python中能否实现循环中ctrl+c跳出循环? python怎么多行注释 404 Not Found 404 Not Found python2.X中CTRL-Z(^Z) python datepickerctrl怎么取出四位年份的日期 python 多线程 Ctrl + c 强行停止后会锁死吗 怎样保存python文件 红领巾的来历 剪短一点的 剪映剪同款可以原版搬抖音吗 淘宝购物金600元啥意思? 天猫消费补贴是什么 天猫消费补贴怎么计算 网络互联的设备有哪些? win7系统如何录屏 win7电脑如何录屏 win7有录屏功能吗