进程,进程

一,结束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

 

posted @   许光宗  阅读(140)  评论(0编辑  收藏  举报
编辑推荐:
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
阅读排行:
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
点击右上角即可分享
微信分享提示