標籤:result 多少 target 進一步 會同 開始 結果 range 引用
# 進程池#為什麼要有進程池? #在程式實際處理任務過程中,忙時會有成千上萬的任務需要被執行,閑時可能只有零星任務.#那麼在成千上萬個任務需要執行的時候,我們就需要去建立成千上萬個進程麼?#首先,建立進程需要消耗時間,銷毀進程也需要消耗時間.第二即便開啟成千上萬的進程#作業系統也不能讓他們同時執行,這樣反而影響程式的效率.因此我們不能無限的根據#任務開啟或者任務結束. #在這裡,要給大家結束一個進程池的概念,定義好一個池子,在裡面放上固定數量#的進程,有需要來了,就在一個池子中的進程來處理任務,等到任務處理完畢,進程並不關閉#而是將進程放回池中繼續等待任務.如果有很多任務需要執行,池中進程的數量不夠,任務就需要#等待之前的進程執行任務完畢歸來,拿到空閑進程才能繼續執行.這樣增加作業系統的調度難度# 還節省了開閉進程的時間,也一定程度上能夠實現並發效果# multiprocessing.Pool 模組#Pool([numprocess [,initializer [,initargs]]]):建立進程池# 參數介紹#numprocess:要建立的進程數,如果省略,將預設使用cpu_count()的值(這是os模組的一個方法)#initializer:是每個背景工作處理序啟動時要執行的可調用對象,預設為None#initargs:是要傳給initializer的參數組# 主要方法有三個:# p = Pool#1.p.apply(func [,args [,kwargs]]):在一個池背景工作處理序中執行func(*args,**kwargs),然後返回結果#注意:此操作並不會在所有池背景工作處理序中執行func函數.如果要通過不同參數並發地執行func函數#必須從不同線程調用p.apply()函數或者使用p.apply_async()# 同步,只有func被執行完後才會繼續執行代碼,傳回值為func的return值#同步處理任務,進程池中的所有進程都是普通進程# 2. p.map(self,func,iterable,chunksize=None):# 非同步,內建close和join,傳回值為func返回組成的列表# 3. p.apply_async(func [,args [,kwargs]]):在一個池中背景工作處理序中執行func(*args,**kwargs)# 然後返回結果#此方法的結果是AsyncResult類的執行個體,callback是可調用對象,接收輸入參數,當func的結果變為可用是# 將結果傳遞給callback. callback禁止執行任何阻塞操作,否者將接收其他非同步作業結果# 非同步,當func被註冊進入一個進程後,程式就繼續向下執行,返回一個對象,這個對象有get方法可以取到值# obj.get()會阻塞,知道對應的func執行完畢拿到結果.需要先close和join來保持多進程和主進程的代碼同步性# 非同步處理任務時,進程池中的所有進程都是守護進程# 有回呼函數 callback# 4. p.close():關閉進程池,防止進一步操作.如果所有操作持續掛起,它們將在背景工作處理序終止前wanc# 5. p.join():等待所有背景工作處理序退出.此方法只能在close()或teminate()之後調用# 其它方法 # 1.方法apply_async()和map_async()的傳回值是AsyncResul的執行個體obj # 2.obj.get():返回結果,如果有必要則等待結果到達.timeout是可選的.如果 #在指定時間內還沒有到達,將引發異常.如果遠程操作中引發了異常,它將在調用此方法時再次被引發 # 3.obj.ready():如果調用完成,返回True # 4.obj.successful():如果調用完成且沒有引發異常,它將在調用此方法時再次被引用 # 5.obj.wait([timeout]):等待結果變為可用 # 6.obj.terminate():立即終止所有背景工作處理序,同時不執行任何清理或結束任何掛起工作.如果p被記憶體回收 #將自動調用此函數# p.map進程池和進程效率測試# from multiprocessing import Pool,Process# import os,time## def func(num):# num += 1# print(num)## if __name__ == ‘__main__‘:# p = Pool(5) # 開進程池中進程的個數5個# start = time.time() # 進程池中任務開始計時# p.map(func,[i for i in range(100)]) # 進程池中的map方法# p.close() # 指不允許向進程池中新增工作# p.join() # 等待進程池中所有進程執行完所有任務# print("進程池中任務的效率:",time.time() - start)## start = time.time() # 普通進程開始計時# p_l = []# for i in range(100):# p1 = Process(target=func,args=(i,))# p1.start()# p_l.append(p1)# [p1.join() for p1 in p_l]# print("多進程的任務效率:",time.time() - start)# #p.apply()是指讓進程池中的進程,同步的幫你做任務# #p.apply_async()是指讓進程池中的進程,非同步幫你做任務# 結果是進程池任務呢0.13 多進程任務5.1# 進程池的同步調用 1# from multiprocessing import Pool,Process# import time## def func(num):# num += 1# return num# def func1(num1):# num1 -= 1# return num1## if __name__ == ‘__main__‘:# p = Pool(5)# start = time.time()# for i in range(100):# ret1 = p.apply(func1,args=(i,))# ret = p.apply(func,args=(i,)) # 同步處理100個任務,同步指不管多少個任務都是一個一個進# print(ret,ret1)## print(time.time() - start)# 進程池的同步調用二# from multiprocessing import Pool# import time,os## def work(n): # 接收i的傳參# print(‘%s run‘ %os.getpid()) # 擷取pid# time.sleep(3)# return n**2## if __name__ == ‘__main__‘:# p = Pool(5) # 進程池開5個進程# ret_l = []# for i in range(10):## res = p.apply(work,args=(i,)) # 同步調用,直到本次任務執行完畢拿到res,任務# print(res)# ret_l.append(res)# #work執行的過程中可能有阻塞也有可能沒有阻塞# #但不管該任務是否存在阻塞,同步調用都會在原地等待# print(ret_l)### 進程池非同步處理任務# from multiprocessing import Pool# import time# def func(num):# num += 1# return num## if __name__ == ‘__main__‘:# p = Pool(5)# start = time.time()# lst = []# for i in range(100):## ret = p.apply_async(func,args=(i,)) # 非同步處理100個任務,非同步值,進程池中有五個進程,一下可以處理五個任務# #print(ret) # 返回 進程池對象地址通過get擷取函數具體的值# print(ret.get())# lst.append(ret)# p.close() #關閉# p.join()# #print(lst)# for i in lst:# new_ret = i.get() # 通過get擷取結果# #print(new_ret)# print(time.time() - start)## 進程池非同步處理任務二# from multiprocessing import Pool# import time,os## def work(n):# print(‘%s run‘ %os.getpid())# return n**2## if __name__ == ‘__main__‘:# p = Pool(5) # 進程池開五個進程# ret_lst = []# for i in range(10):# ret = p.apply_async(work,args=(i,)) # 非同步運行,根據進程池中的進程數,每次# #最多執行5個子進程在非同步執行# #返回結果加入列表,歸還進程,之後執行新任務# #注意:進程池中的五個進程不會同時開啟或者同時結束# #而是執行完一個就釋放一個進程,這個進程去接收新的任務# ret_lst.append(ret)# #非同步apply_async用法:如果使用非同步提交任務,主進行需要使用join,等待進程池內# #任務都處理完,然後可以用get收集結果# #否者,主進程結束,進程池可能還沒來得及執行,也就跟著主進程一起結束# p.close()# p.join()# for i in ret_lst:# new_ret = i.get() # 擷取結果# #使用get來擷取apply_async的結果,如果是apply,則沒有get方法# #因為apply是同步執行,立刻擷取結果,也根本無需get# print(new_ret)# 進程池同步執行和非同步執行的效率對比# from multiprocessing import Pool# import time## def func(num):# num += 1# return num### if __name__ == ‘__main__‘:# p = Pool(5)# start = time.time()# for i in range(10000):# ret = p.apply(func,args=(i,)) # 進程池同步執行# print(‘進程池同比執行時間:‘,time.time() - start)## start = time.time()# for i in range(10000):# ret1 = p.apply_async(func,args=(i,)) # 進程池非同步執行# p.close()# p.join()# print("進程池非同步執行時間:",time.time() - start)# 結果:進程池執行相同的任務量,非同步執行比同步執行塊# 回呼函數 #需要回呼函數的情境:進程池中任何一個任務一旦處理完了,就立即告知進程 #我好了餓,你可以處理我的結果.主進程則掉用一個函數去處理該結果,該函數即會調函數 #我們可以把耗時間(阻塞)的任務放到進程池中,然後指定回呼函數(主進程複雜執行) #這樣主進程在執行回調數時就省去I/O的過程,直接拿到的是任務的結果 #如果在主進程中等待進程池中所有任務都執行完畢後,再統一處理結果,則無需回呼函數
Python進程池