进程,进程

一,结束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 @ 2018-02-06 15:39  许光宗  阅读(136)  评论(0编辑  收藏  举报