38、线程及其方法
线程池
1、为什么会有进程池?
开启过多的进程1)开启进程浪费时间2)操作系统调度太多的进程也会影响效率
2、开进程池
有几个现成的进程在池子里,有任务来了,就用池子里的进程取处理任务
任务处理完之后,就把进程放回到池子里,池子里的进程就能取处理其他的任务了
当所有的额任务处理完了,进程池关闭,回收所有进程。
3、开启的进程数:CPU的数量+1
下面是关于进程池异步调用和同步调用。
import time from multiprocessing import Pool def fun(i): time.sleep(1) i+=1 print(i) if __name__ =='__main__': p=Pool(4) for i in range(10): p.apply_async(fun,args=(i,)) #异步调用 apply是同步调用 p.close() #没有这句话,主进程会先结束,留下子进程残留,回收麻烦。这句话的意思是关闭进程池,不能再往进程池中添加任务了 p.join() #阻塞等待,等待进程池中所有进程结束
进程池get用法:apply_async有get方法,apply没有,所以可以把所有返回的结果统一放入一个列表中,进程池中所有程序结束在循环打印结果。
import time from multiprocessing import Pool def fun(i): time.sleep(1) i+=1 return i if __name__ =='__main__': p=Pool(4) res_l=[] for i in range(10): res=p.apply_async(fun,args=(i,)) res_l.append(res) p.close() p.join() [print(j.get() )for j in res_l]
关于map的用法:
import time from multiprocessing import Pool def fun(i): time.sleep(1) i+=1 return i if __name__ =='__main__': p=Pool(4) ret=p.map(fun,range(10)) #map传的必须是可迭代对象 print(ret)
回调函数:返回值(结果)传给回调函数,回调函数执行。回调函数是在主进程中执行的,回掉函数不能传参,只能接受多进程中函数的返回值。
from multiprocessing import Pool def fun(i): return i*'*' def call(arg): print(arg) if __name__ =='__main__': p=Pool(4) for i in range(10): p.apply_async(fun,args=(i,),callback=call) p.close() p.join()
回调函数在网页处理中的作用:
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()