多进程之进程池,回调函数
*****生产者消费者模型:
程序中有两类角色、
一类负责生产数据--生产者
一类负责处理数据--消费者
引入生产者消费者模型为了解决的问题是:平衡生产者与消费者之间的速度差
实现方法:生产者---》队列---》消费者(生产者消费者解耦合)
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()
共享内存--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)
*****进程池--主程序结束,进程池结束
同步调用--提交完任务后,在原地等任务结束,一旦结束,可以拿到结果
阻塞--进程的一种状态
正在运行的程序遇到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了。
分布式开发:只要提供一台电脑作为版本集中存的服务器放就够了,
但这个服务器的作用仅仅是用来方便“交换”大家的修改,没有它也一样干活,只是交换修改不方便而已。
而每一台电脑有各自独立的开发环境,不需要联网,本地直接运行,相对集中式安全系数高很多。
浙公网安备 33010602011771号