进程,进程
一,结束while循环
from multiprocessing import Process from multiprocessing import Queue import time import random def aa(q,food): for i in range(10): q.put('%s%s号'%(food,i)) print('%s%s号'%(food,i)) time.sleep(random.random()) def bb(q,man): while True: print('%s吃了'%(man),q.get()) if __name__=='__main__': q=Queue() p1=Process(target=aa,args=(q,'泔水')) p1.start() p2 = Process(target=aa, args=(q,'馒头')) p2.start() c1 = Process(target=bb, args=(q,'小高')) c1.start() c2 = Process(target=bb, args=(q,'小赵')) c2.start() c3 = Process(target=bb, args=(q,'小陈')) c3.start()
C:\Users\hc\AppData\Local\Programs\Python\Python36\python3.exe C:/s9/37day/37.py
泔水0号
馒头0号
小高吃了 泔水0号
小高吃了 馒头0号
泔水1号
小高吃了 泔水1号
馒头1号
小赵吃了 馒头1号
馒头2号
小陈吃了 馒头2号
泔水2号
小高吃了 泔水2号
泔水3号
小赵吃了 泔水3号
馒头3号
小陈吃了 馒头3号
馒头4号
小高吃了 馒头4号
馒头5号
小赵吃了 馒头5号
泔水4号
小陈吃了 泔水4号
泔水5号
小高吃了 泔水5号
馒头6号
小赵吃了 馒头6号
泔水6号
小陈吃了 泔水6号
小高吃了 馒头7号
馒头7号
泔水7号
小赵吃了 泔水7号
馒头8号
小陈吃了 馒头8号
泔水8号
小高吃了 泔水8号
馒头9号
小赵吃了 馒头9号
泔水9号
小陈吃了 泔水9号
由此可见,当生产者结束了以后,消费者并没有退出循环
from multiprocessing import Process from multiprocessing import Queue import time import random def aa(q,food): for i in range(10): q.put('%s%s号'%(food,i)) print('%s%s号'%(food,i)) time.sleep(random.random()) q.put(None) q.put(None) q.put(None) def bb(q,man): while True: d=q.get() if d==None:break print('%s吃了'%(man),d) if __name__=='__main__': q=Queue() p1=Process(target=aa,args=(q,'泔水')) p1.start() p2 = Process(target=aa, args=(q,'馒头')) p2.start() c1 = Process(target=bb, args=(q,'小高')) c1.start() c2 = Process(target=bb, args=(q,'小赵')) c2.start() c3 = Process(target=bb, args=(q,'小陈')) c3.start()
C:\Users\hc\AppData\Local\Programs\Python\Python36\python3.exe C:/s9/37day/37.py
泔水0号
馒头0号
小高吃了 泔水0号
小高吃了 馒头0号
馒头1号
小高吃了 馒头1号
泔水1号
小赵吃了 泔水1号
泔水2号
小陈吃了 泔水2号
馒头2号
小高吃了 馒头2号
馒头3号
小赵吃了 馒头3号
馒头4号
小陈吃了 馒头4号
馒头5号
小高吃了 馒头5号
泔水3号
小赵吃了 泔水3号
泔水4号
小陈吃了 泔水4号
泔水5号
小高吃了 泔水5号
泔水6号
小赵吃了 泔水6号
泔水7号
小陈吃了 泔水7号
馒头6号
小高吃了 馒头6号
泔水8号
小赵吃了 泔水8号
泔水9号
小陈吃了 泔水9号
馒头7号
小高吃了 馒头7号
馒头8号
馒头9号
Process finished with exit code 0
加个判断就能解决这个问题,可是新的问题又来了,在你不知道有几个消费者,或者消费者过多的情况下,你该如何呢?
from multiprocessing import Process from multiprocessing import JoinableQueue import time import random def aa(q,food): for i in range(10): q.put('%s%s号'%(food,i)) print('%s%s号'%(food,i)) time.sleep(random.random()) q.join() def bb(q,man): while True: d=q.get() print('%s吃了'%(man),d) q.task_done() if __name__=='__main__': q=JoinableQueue() p1=Process(target=aa,args=(q,'泔水')) p1.start() p2 = Process(target=aa, args=(q,'馒头')) p2.start() c1 = Process(target=bb, args=(q,'小高')) c1.daemon=True c1.start() c2 = Process(target=bb, args=(q,'小赵')) c2.daemon = True c2.start() c3 = Process(target=bb, args=(q,'小陈')) c3.daemon = True c3.start() p1.join() p2.join()
C:\Users\hc\AppData\Local\Programs\Python\Python36\python3.exe C:/s9/37day/37.py
泔水0号
馒头0号
小高吃了 泔水0号
小高吃了 馒头0号
馒头1号
小高吃了 馒头1号
馒头2号
小赵吃了 馒头2号
馒头3号
小高吃了 馒头3号
泔水1号
小陈吃了 泔水1号
馒头4号
小赵吃了 馒头4号
泔水2号
小高吃了 泔水2号
馒头5号
小陈吃了 馒头5号
泔水3号
小赵吃了 泔水3号
馒头6号
小高吃了 馒头6号
小陈吃了 泔水4号
泔水4号
泔水5号
小赵吃了 泔水5号
泔水6号
小高吃了 泔水6号
馒头7号
小陈吃了 馒头7号
泔水7号
小赵吃了 泔水7号
馒头8号
小高吃了 馒头8号
馒头9号
小陈吃了 馒头9号
泔水8号
小赵吃了 泔水8号
小高吃了 泔水9号
泔水9号
Process finished with exit code 0
这里,引用一个模块,task_done当消费者完成以后,将这个发送给生产者,q.join生产者接收后,结束,由于消费者事先被设置成守护进程,主进程结束,随之结束,
ipc机制
二,pipe管道
from multiprocessing import Pipe p1,p2=Pipe() p1.send('hello') print(p2.recv()) p2.send('heo') print(p1.recv()) print(p1.recv())
C:\Users\hc\AppData\Local\Programs\Python\Python36\python3.exe C:/s9/37day/37.py
hello
heo
管道支持双向通信,但是,当接收方大于发送方的时候,程序会被阻塞在这里
三进程池
map,,拿到返回值,存放在一个列表中
传参的时候,传的必须是一个可迭代的
import time from multiprocessing import Pool def fun(i): time.sleep(1) i+=1 return i if __name__ == '__main__': s = time.time() p = Pool(4) ret = p.map(fun,range(10)) print(ret) print(time.time() - s)
C:\Users\hc\AppData\Local\Programs\Python\Python36\python3.exe C:/s9/38day/39.py [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] 3.408907413482666 Process finished with exit code 0
from multiprocessing import Process from multiprocessing import Pool import time def aa(i): i+=1 if __name__=='__main__': p=Pool(5) start=time.time() p.map(aa,range(19)) p.close() p.join() print(time.time()-start) l=[] start=time.time() for i in range(19): p=Process(target=aa,args=(i,)) p.start() l.append(p) [i.join() for i in l] print(time.time() - start)
C:\Users\hc\AppData\Local\Programs\Python\Python36\python3.exe C:/s9/37day/37.py 0.21370530128479004 1.504941463470459 Process finished with exit code 0
通过对比,很明显,用了进程池和不用的差距,
1,基于进程池下的同步提交
def aa(i): time.sleep(1) i+=1 print(i) if __name__=='__main__': p=Pool(5) for i in range(19): p.apply(aa, args=(i,))
2,基于进程池下的异步提交
from multiprocessing import Pool import time import time def aa(i): time.sleep(1) i+=1 print(i) if __name__=='__main__': p=Pool(5) l=[] for i in range(19): p.apply_async(aa, args=(i,)) p.close() p.join()
Manager模块里提供了很多数据类型来进行进程之间的数据共享,但是几乎数据都不安全
from multiprocessing import Process def func(dic): dic['count']+=1 print(dic) # m=Manager() # dic=m.dict() dic={} dic['count'] =0 if __name__=='__main__': for i in range(2): p=Process(target=func,args=(dic,)) p.start() p.join()
C:\Users\hc\AppData\Local\Programs\Python\Python36\python3.exe C:/s9/38day/39.py {'count': 1} {'count': 1} Process finished with exit code 0
正常情况下进程之间数据是不共享的,所以一直是1
from multiprocessing import Manager from multiprocessing import Process def func(dic): dic['count']+=1 print(dic) if __name__=='__main__': m = Manager() dic = m.dict() dic['count'] = 0 for i in range(10): p=Process(target=func,args=(dic,)) p.start() p.join()
C:\Users\hc\AppData\Local\Programs\Python\Python36\python3.exe C:/s9/38day/39.py {'count': 1} {'count': 2} {'count': 3} {'count': 4} {'count': 5} {'count': 6} {'count': 7} {'count': 8} {'count': 9} {'count': 10} Process finished with exit code 0
Manager的作用就是是进程之间的数据可以共享
回调函数:
回调函数是在主进程中完成的,不能传参,只能接受多进程中的返回值
import os import time from multiprocessing import Pool def func(i): print('子进程%s:%s'%(i,os.getpid())) return i*'*' def call(arg): print('回调 :',os.getpid()) print(arg) if __name__ == '__main__': print('---->',os.getpid()) p = Pool(5) for i in range(10): p.apply_async(func,args=(i,),callback=call) p.close() p.join()
C:\Users\hc\AppData\Local\Programs\Python\Python36\python3.exe C:/s9/38day/39.py ----> 11904 子进程0:7060 回调 : 11904 子进程1:9504 子进程2:7060 回调 : 11904 ** 子进程3:7060 子进程4:9504 回调 : 11904 * 子进程5:7060 回调 : 11904 *** 回调 : 11904 **** 子进程6:9504 回调 : 11904 ***** 回调 : 11904 ****** 子进程7:7060 回调 : 11904 ******* 子进程8:9504 回调 : 11904 ******** 子进程9:7060 回调 : 11904 ********* Process finished with exit code 0
关于回调函数的一个实例:
用到requests模块
import requests from multiprocessing import Pool def get_url(url): ret = requests.get(url) return {'url':url, 'status_code':ret.status_code, 'content':ret.text} def parser(dic): print(dic['url'],dic['status_code'],len(dic['content'])) # 把分析结果写到文件里 if __name__ == '__main__': url_l = [ 'http://www.baidu.com', 'http://www.sogou.com', 'http://www.hao123.com', 'http://www.yangxiaoer.cc', 'http://www.python.org' ] p = Pool(4) for url in url_l: p.apply_async(get_url,args=(url,),callback=parser) p.close() p.join()
C:\Users\hc\AppData\Local\Programs\Python\Python36\python3.exe C:/s9/38day/39.py http://www.baidu.com 200 2381 http://www.sogou.com 200 22431 http://www.hao123.com 200 498845 http://www.yangxiaoer.cc 200 35667 http://www.python.org 200 48871 Process finished with exit code 0
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库