在实际操作过程中python可以对进程进行很好的管控,但是对线程来说有的时候却无能为力,比如我利用多线程正在执行一个文件搜索的任务,它需要遍历所有目录需要花很长时间才能遍历完,但是一旦出现我们想要的结果时,我们就终止搜索岂不是更好,ctrl+c就终止所有线程的运行,然后返回主进程不是更符合用户体验。
废话不多说讲讲原理.
思路1:主进程---->子进程{n多个线程} (没有思路2了)
我可以在主进程开一个子进程,然后在子进程里面再来执行线程,如果我想终止所有线程我就直接杀死子进程,岂不美哉,我们来实践一下,、
import signal,os
from multiprocessing import Process,Queue
from threading import Thread,currentThread
from time import *
grand=[0] #用来存孙子进程的pid
flag=[0] #设置跳出chile循环的标志
def quit(signum, frame):
flag[0]=1
print("终止了主进程",grand[0])
try: #使用try是防止程序报错而退出
os.kill(grand[0],signal.SIGILL) #os.kill(pid,signal)
except:
pass
def threadn():
global counter
while True:
#print("tid=",currentThread())
print("child_pid=",os.getpid())
sleep(2)
def create_thread_pool():
ta=[0 for i in range(10)] #创建一个长度为10的列表用于存储10个线程名
for i in range(10): #创建10个线程
ta[i]=Thread(target=threadn)
for ii in range(10):
ta[ii].start()
for iii in range(10):
ta[iii].join()
def process0(q): #子进程process1
q.put_nowait(os.getpid())
print("grand pid=",os.getpid())
#signal.signal(signal.SIGINT,quit) #接收中断信号ctrl+c
create_thread_pool() #我在子进程创建n个线程
if __name__=="__main__":
q=Queue() #实例化消息队列
while True:
print("main pid=",os.getpid())
name=input("please input name:")
p0=Process(target=process0,args=(q,))
p0.start()
sleep(1)
grand[0]=q.get_nowait()
signal.signal(signal.SIGINT,quit) #接收中断信号ctrl+c
while 1:#循环等待不要用join()防止陷入子进程,主进程无法得到时间片而不能响应中断
if flag[0]:#设置跳出循环的标志,中断处理函数会改变这个值
break
sleep(1)
上图中的grand[0]理解为child[0]因为最开始我创建了孙子进程所以名称有点出入,在上面代码看到grand一律当做子进程(child)
下图在程序运行时按ctrl+c就可以结束子进程
2关于Python3多进程程序打包问题
关于打包后子进程无法运行需要multiprocessing的一个freeze_support模块,然后打包后的exe
才能正常输出,否则不会显示任何内容,如下引用模块即可
from multiprocessing freeze_support
if __name__=='__main__':
freeze_support() #初始化实例
3.消息队列需要注意一下
有时需要用q.get_nowait()不会使代码进入阻塞队列 ,q.get()则会
4.纠正一下信号量的问题
网上好多是使用的SIGKILL 而实际是SIGILL 少了一个K,大家不要被误导了
反正我是被我误导过,才知道这个错误,坑了我半天编译器一直提醒我signal没有这个属性
5.反馈与建议
第一次写博客,如果以上文章有错误请多多包涵!❥(^_-),有什么不不明白我没说清楚的地方,可以给我留言