python使用多進(jìn)程的實(shí)例詳解
python多線程適合IO密集型場景,而在CPU密集型場景,并不能充分利用多核CPU,而協(xié)程本質(zhì)基于線程,同樣不能充分發(fā)揮多核的優(yōu)勢。
針對(duì)計(jì)算密集型場景需要使用多進(jìn)程,python的multiprocessing與threading模塊非常相似,支持用進(jìn)程池的方式批量創(chuàng)建子進(jìn)程。
•創(chuàng)建單個(gè)Process進(jìn)程(使用func)
只需要實(shí)例化Process類,傳遞函數(shù)給target參數(shù),這點(diǎn)和threading模塊非常的類似,args為函數(shù)的參數(shù)
import os from multiprocessing import Process # 子進(jìn)程要執(zhí)行的代碼 def task(name): print('run child process %s (%s)...' % (name, os.getpid())) if __name__ == '__main__': print('parent process %s.' % os.getpid()) p = Process(target=task, args=('test',)) p.start() p.join() print('process end.')
•創(chuàng)建單個(gè)Process進(jìn)程(使用class)
繼承Process類,重寫run方法創(chuàng)建進(jìn)程,這點(diǎn)和threading模塊基本一樣
import multiprocessing import os from multiprocessing import current_process class Worker(multiprocessing.Process): def run(self): name = current_process().name # 獲取當(dāng)前進(jìn)程的名稱 print('run child process <%s> (%s)' % (name, os.getpid())) print('In %s' % self.name) return if __name__ == '__main__': print('parent process %s.' % os.getpid()) p = Worker() p.start() p.join() print('process end.') * 停止進(jìn)程
terminate()結(jié)束子進(jìn)程,但是會(huì)導(dǎo)致子進(jìn)程的資源無法釋放掉,是不推薦的做法,因?yàn)榻Y(jié)束的時(shí)候不清楚子線程的運(yùn)行狀況,有很大可能性導(dǎo)致子線程在不恰當(dāng)?shù)臅r(shí)刻被結(jié)束。
import multiprocessing import time def worker(): print('starting worker') time.sleep(0.1) print('finished worker') if __name__ == '__main__': p = multiprocessing.Process(target=worker) print('執(zhí)行前:', p.is_alive()) p.start() print('執(zhí)行中:', p.is_alive()) p.terminate() # 發(fā)送停止號(hào) print('停止:', p.is_alive()) p.join() print('等待完成:', p.is_alive())
•直接創(chuàng)建多個(gè)Process進(jìn)程
import multiprocessing def worker(num): print(f'Worker:%s %s', num) return if __name__ == '__main__': jobs = [] for i in range(5): p = multiprocessing.Process(target=worker, args=(i,)) jobs.append(p) p.start()
•使用進(jìn)程池創(chuàng)建多個(gè)進(jìn)程
在利用Python進(jìn)行系統(tǒng)管理的時(shí)候,特別是同時(shí)操作多個(gè)文件目錄,或者遠(yuǎn)程控制多臺(tái)主機(jī),并行操作可以節(jié)約大量的時(shí)間。當(dāng)被操作對(duì)象數(shù)目不大時(shí),可以直接利用multiprocessing中的Process動(dòng)態(tài)成生多個(gè)進(jìn)程,十幾個(gè)還好,但如果是上百個(gè),上千個(gè)目標(biāo),手動(dòng)的去限制進(jìn)程數(shù)量卻又太過繁瑣,此時(shí)可以發(fā)揮進(jìn)程池的功效。
Pool可以提供指定數(shù)量的進(jìn)程供用戶調(diào)用,當(dāng)有新的請(qǐng)求提交到pool中時(shí),如果池還沒有滿,那么就會(huì)創(chuàng)建一個(gè)新的進(jìn)程用來執(zhí)行該請(qǐng)求;但如果池中的進(jìn)程數(shù)已經(jīng)達(dá)到規(guī)定最大值,那么該請(qǐng)求就會(huì)等待,直到池中有進(jìn)程結(jié)束,才會(huì)創(chuàng)建新的進(jìn)程來它。
import os import random import time from multiprocessing import Pool from time import ctime def task(name): print('start task %s (%s)...' % (name, os.getpid())) start = time.time() time.sleep(random.random() * 3) print('end task %s runs %0.2f seconds.' % (name, (time.time() - start))) if __name__ == '__main__': print('parent process %s.' % os.getpid()) p = Pool() # 初始化進(jìn)程池 for i in range(5): p.apply_async(task, args=(i,)) # 追加任務(wù) apply_async 是異步非阻塞的,就是不用等待當(dāng)前進(jìn)程執(zhí)行完畢,隨時(shí)根據(jù)系統(tǒng)調(diào)度來進(jìn)行進(jìn)程切換。 p.close() p.join() # 等待所有結(jié)果執(zhí)行完畢,會(huì)等待所有子進(jìn)程執(zhí)行完畢,調(diào)用join()之前必須先調(diào)用close() print(f'all done at: {ctime()}')
如果關(guān)心每個(gè)進(jìn)程的執(zhí)行結(jié)果,可以使用返回結(jié)果的get方法獲取,代碼如下
import os import random import time from multiprocessing import Pool, current_process from time import ctime def task(name): print('start task %s (%s)...' % (name, os.getpid())) start = time.time() time.sleep(random.random() * 3) print('end task %s runs %0.2f seconds.' % (name, (time.time() - start))) return current_process().name + 'done' if __name__ == '__main__': print('parent process %s.' % os.getpid()) result = [] p = Pool() # 初始化進(jìn)程池 for i in range(5): result.append(p.apply_async(task, args=(i,))) # 追加任務(wù) apply_async 是異步非阻塞的,就是不用等待當(dāng)前進(jìn)程執(zhí)行完畢,隨時(shí)根據(jù)系統(tǒng)調(diào)度來進(jìn)行進(jìn)程切換。 p.close() p.join() # 等待所有結(jié)果執(zhí)行完畢 for res in result: print(res.get()) # get()函數(shù)得出每個(gè)返回結(jié)果的值 print(f'all done at: {ctime()}')
總結(jié)
以上所述是小編給大家介紹的python使用多進(jìn)程的實(shí)現(xiàn)代碼,希望對(duì)大家有所幫助,如果大家有任何疑問請(qǐng)給我留言,小編會(huì)及時(shí)回復(fù)大家的。在此也非常感謝大家對(duì)腳本之家網(wǎng)站的支持!
相關(guān)文章
解決新版Pycharm中Matplotlib圖像不在彈出獨(dú)立的顯示窗口問題
今天小編就為大家分享一篇解決新版Pycharm中Matplotlib圖像不在彈出獨(dú)立的顯示窗口問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2019-01-01Python實(shí)現(xiàn)矩陣轉(zhuǎn)置的方法分析
這篇文章主要介紹了Python實(shí)現(xiàn)矩陣轉(zhuǎn)置的方法,結(jié)合實(shí)例形式較為詳細(xì)的分析了Python實(shí)現(xiàn)矩陣轉(zhuǎn)置的相關(guān)操作技巧,需要的朋友可以參考下2017-11-11Python一行代碼實(shí)現(xiàn)自動(dòng)發(fā)郵件功能
最近在自己學(xué)習(xí)Python爬蟲,學(xué)到了用Python發(fā)送郵件,覺得這個(gè)可能以后比較實(shí)用。所以這篇文章主要給大家介紹了如何通過Python一行代碼實(shí)現(xiàn)自動(dòng)發(fā)郵件功能的相關(guān)資料,需要的朋友可以參考下2021-05-05Python實(shí)現(xiàn)自動(dòng)化郵件發(fā)送過程詳解
這篇文章主要介紹了如何利用Python實(shí)現(xiàn)自動(dòng)化郵件發(fā)送,可以讓你擺脫繁瑣的重復(fù)性業(yè)務(wù),可以節(jié)省非常多的時(shí)間。感興趣的小伙伴可以試一試2022-01-01詳解如何修改jupyter notebook的默認(rèn)目錄和默認(rèn)瀏覽器
這篇文章主要介紹了詳解如何修改jupyter notebook的默認(rèn)目錄和默認(rèn)瀏覽器,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2021-01-01