多进程之进程池,回调函数

*****生产者消费者模型:
程序中有两类角色、
一类负责生产数据--生产者
一类负责处理数据--消费者
引入生产者消费者模型为了解决的问题是:平衡生产者与消费者之间的速度差
实现方法:生产者---》队列---》消费者(生产者消费者解耦合)
from multiprocessing import Process,Queue
import time,random

def producer(name,q):
    for i in range(10):
        time.sleep(random.randint(1,3))
        res = "money %s"%i
        q.put(res)
        print("大神 %s 生产了 %s"%(name,res))
def consumer(name,q):
    while True:
        res = q.get()
        if res is None:break
        time.sleep(random.randint(1,3))
        print("%s 拿到了 %s"%(name,res))

if __name__ == '__main__':
    q = Queue()
    p1 = Process(target=producer,args=("alex",q))
    c1 = Process(target=consumer,args=("lu",q))

    p1.start()
    c1.start()
    p1.join()

    q.put(None)
生产者消费者模型--多个生产者,多个消费者

 

JoinableQueue
from multiprocessing import Process,JoinableQueue
import time,random

def producer(name,q):
    for i in range(2):
        time.sleep(random.randint(1,3))
        res = "money %s"%i
        q.put(res)
        print("大神 %s 生产了 %s"%(name,res))
    q.join()    # producer等待q结束

def consumer(name,q):
    while True:
        res = q.get()
        if res is None:break
        time.sleep(random.randint(1,3))
        print("%s 拿到了 %s"%(name,res))
        q.task_done()   # 放在get之后,给生产者发送消息,当q里面没有东西之后,join就执行,结束


if __name__ == '__main__':
    q = JoinableQueue()
    p1 = Process(target=producer,args=("alex",q))
    p2 = Process(target=producer, args=("egon", q))
    p3 = Process(target=producer, args=("joe", q))
    c1 = Process(target=consumer,args=("lu",q))
    c2 = Process(target=consumer, args=("tu", q))

    c1.daemon = True
    c2.daemon = True

    p1.start()
    p2.start()
    p3.start()
    c1.start()
    c2.start()

    p1.join()
    p2.join()
    p3.join()
生产者消费者模型--多个生产者,多个消费者-- JoinableQueue

 

共享内存--Manager模块
from multiprocessing import Process,Manager,Lock

def work(d,lock):
    with lock:
        temp = d["count"]
        d["count"] = temp - 1

if __name__ == '__main__':
    p_list = []
    m = Manager()
    lock = Lock()
    d = m.dict({"count":10})
    # l = m.list([1,2,3,45,]) #--可以创建任意数据类型
    for i in range(10):
        p = Process(target=work,args=(d,lock))
        p_list.append(p)
        p.start()

    for p in p_list:
        p.join()

    print(d)
共享内存--Manager模块

 

*****进程池--主程序结束,进程池结束
同步调用--提交完任务后,在原地等任务结束,一旦结束,可以拿到结果
阻塞--进程的一种状态
正在运行的程序遇到io 进入阻塞状态

异步调用--提交完任务后,不会在原地等任务结束,会继续提交任务,等到所有任务结束后,get到结果
非阻塞--可能是运行状态,也可能是就绪状态

方法:
p.apply(func[, args[, kwargs]]):在一个池工作进程中执行func(*args,**kwargs), 然后返回结果。
    需要强调的是:此操作并不会在所有池工作进程中并执行func函数。
    如果要通过不同参数并发地执行func函数,必须从不同线程调用p.apply()函数或者使用p.apply_async()
p.apply_async(func[, args[, kwargs]]):在一个池工作进程中执行func(*args,**kwargs), 然后返回结果。
    此方法的结果是AsyncResult类的实例,callback是可调用对象,接收输入参数。
    当func的结果变为可用时,将理解传递给callback。callback禁止执行任何阻塞操作,否则将接收其他异步操作中的结果。

p.close(): 关闭进程池,防止进一步操作。如果所有操作持续挂起,它们将在工作进程终止前完成
P.jion(): 等待所有工作进程退出。此方法只能在close()或teminate()之后调用

 

from multiprocessing import Pool
import os,time,random

def work(n):
    print("%s is working"%os.getpid())
    time.sleep(random.randint(1,3))
    return n**2

if __name__ == '__main__':
    p = Pool(4) # 不写参数就是默认cpu个数
    obj_l = []
    for i in range(10):
        # 同步调用
        # res = p.apply(work,args=(i,))
        # print(res)

        # 异步调用
        obj = p.apply_async(work,args=(i,))
        obj_l.append(obj)

    p.close()
    p.join()    # 主程序等待进程池结束
    for obj in obj_l:
        print(obj.get())

    print("主进程")
进程池

 

回调函数
参数只有一个,而且是前面进程的函数的返回值,运行时间必须要小于前面函数的时间
from multiprocessing import Pool,Process
import requests     # 安装requests模块 python -m pip install requests
import os,random,time

def get(url):
    print("%s GET %s" %(os.getpid(),url))
    response = requests.get(url)
    time.sleep(random.randint(1,3))
    if response.status_code == 200:
        print("%s DONE %s" %(os.getpid(),url))
        return {"url":url,"text":response.text}

def parse(dic):
    print("%s PARSE %s"%(os.getpid(),dic["url"]))
    time.sleep(1)
    res = "%s:%s\n"%(dic["url"],len(dic["text"]))
    with open("db.txt","a") as f:
        f.write(res)

if __name__ == '__main__':
    urls = ['https://www.baidu.com',
        'https://www.python.org',
        'https://www.openstack.org',
        'https://help.github.com/',
        'http://www.sina.com.cn/'
    ]
    p = Pool(2)
    objs = []
    for url in urls:
        obj = p.apply_async(get,args=(url,),callback=parse)# parse就是回调函数
        # 主进程负责干回调函数的活
        objs.append(obj)

    p.close()
    p.join()
回调函数

 

集中式和分布式

集中式开发:是将项目集中存放在中央服务器中,
在工作的时候,大家只在自己电脑上操作,从同一个地方下载最新版本,然后开始工作,做完的工作再提交给中央服务器保存。
这种方式需要联网,现在云开发就是这样的处理方式。
缺点:
1、如果网络出现异常或者很卡,直接影响工作效率。如果是中央服务器挂了,那就集体喝茶去了。

2、还有一种情况,各自电脑中操作的所有软件工具,都存放在一个中央服务器上(现在流行叫云服务器),
只需要用各自电脑登陆连接到云服务器上,(一般服务器都是用linux),

比如用ps工具,大家其实用的是云服务器中的同一个ps 软件,在使用率高的情况下,ps会出现异常,
当用ps筛选颜色的时候,已经混乱,无法正常选择颜色,这个情况是我在开发中遇到的。
以前我们是每个人用各自安装的ps,但是在这样的环境下用的是同一个ps软件的时候就会有bug。

3、安全度不高,重要的东西都放在一个中央服务器中,如果被黑,那损失就大了。

优点:
1、减少了硬件和软件成本,硬件不用说了,现在流行盒子,一个小盒子只要连上中央服务器即可,以前都是一个个主机箱,那成本大多了。
如果用到工具软件需要收费,只需买一套正版就OK了。


分布式开发:只要提供一台电脑作为版本集中存的服务器放就够了,
但这个服务器的作用仅仅是用来方便“交换”大家的修改,没有它也一样干活,只是交换修改不方便而已。
而每一台电脑有各自独立的开发环境,不需要联网,本地直接运行,相对集中式安全系数高很多。









posted @ 2017-10-12 16:17  chitalu  阅读(209)  评论(0)    收藏  举报