Python使用multiprocessing如何實(shí)現(xiàn)多進(jìn)程
進(jìn)程是操作系統(tǒng)進(jìn)行資源分配和調(diào)度的一個(gè)基本單位。
一、進(jìn)程及多任務(wù)介紹
- 程序:程序是一個(gè)靜態(tài)的概念。在一臺電腦上,我們安裝了很多程序,這些程序是可以運(yùn)行的。比如我們編寫一個(gè)xxx.py程序,它是靜態(tài)的,靜靜的保存在電腦的硬盤中,等待執(zhí)行。
- 進(jìn)程:進(jìn)程是操作系統(tǒng)分配資源的基本單位,一個(gè)程序運(yùn)行起來后,代碼加用到的系統(tǒng)資源稱之為進(jìn)程。比如我們在終端通過 python xxx.py將xxx.py程序運(yùn)行起來,這時(shí)候就開啟了一個(gè)進(jìn)程。
- 多任務(wù):多任務(wù)是指操作系統(tǒng)可以同時(shí)運(yùn)行多個(gè)任務(wù)。在使用一臺電腦時(shí),我們需要同時(shí)做很多的事情,如打開PyCharm寫代碼,打開瀏覽器查API,打開詞典查單詞,這時(shí)候我們同時(shí)打開了多個(gè)程序,每個(gè)程序都在運(yùn)行。對于操作系統(tǒng)來說,每個(gè)正在運(yùn)行的程序都是一個(gè)任務(wù),很多任務(wù)同時(shí)運(yùn)行就是多任務(wù)。
在Python中,可以通過multiprocessing模塊開啟多個(gè)進(jìn)程來幫我們同時(shí)執(zhí)行多任務(wù)。
例如,xxx.py運(yùn)行起來后,至少會(huì)開啟一個(gè)進(jìn)程,這個(gè)進(jìn)程叫主進(jìn)程,如果我們要同時(shí)執(zhí)行多任務(wù),我們可以開啟多個(gè)進(jìn)程來執(zhí)行多任務(wù),這些進(jìn)程叫子進(jìn)程。
既有主進(jìn)程,又有子進(jìn)程,這時(shí)候就是多進(jìn)程。每個(gè)進(jìn)程中可以執(zhí)行一個(gè)或多個(gè)任務(wù),這樣就實(shí)現(xiàn)了多任務(wù)。
補(bǔ)充:
并發(fā):指的是任務(wù)數(shù)多于CPU核數(shù),通過操作系統(tǒng)的各種任務(wù)調(diào)度算法,實(shí)現(xiàn)多個(gè)任務(wù)“一起”執(zhí)行(實(shí)際上,同一時(shí)間只有一個(gè)任務(wù)在執(zhí)行,操作系統(tǒng)是通過時(shí)間片輪詢的方式,輪流讓各個(gè)任務(wù)交替執(zhí)行。
例如:任務(wù)1執(zhí)行0.0001秒,切換到任務(wù)2,任務(wù)2執(zhí)行0.0001秒,再切換到任務(wù)3,執(zhí)行0.0001秒,又切換回任務(wù)1……這樣循環(huán)下去。因?yàn)榍袚Q任務(wù)的速度相當(dāng)快,我們感覺就像所有任務(wù)都在同時(shí)執(zhí)行一樣。)
并行:當(dāng)任務(wù)數(shù)小于或者等于CPU核數(shù)時(shí),每一個(gè)任務(wù)都有對應(yīng)的CPU來處理執(zhí)行,即任務(wù)真的是一起執(zhí)行的(實(shí)際上,我們的電腦上運(yùn)行的任務(wù)數(shù)量非常多,除了我們開啟的任務(wù),還有很多任務(wù)在后臺運(yùn)行著,而CPU數(shù)量是有限的,基本上不可能一個(gè)任務(wù)占一核CPU。由于任務(wù)數(shù)量遠(yuǎn)遠(yuǎn)多于CPU的核心數(shù)量,所以,操作系統(tǒng)會(huì)自動(dòng)把很多任務(wù)輪流調(diào)度到每個(gè)核心上執(zhí)行。)
二、使用multiprocessing實(shí)現(xiàn)多進(jìn)程
from multiprocessing import Process import time def coding(language): """子進(jìn)程要執(zhí)行的代碼""" for i in range(5): print("{} coding".format(language), end=' | ') time.sleep(1) if __name__ == '__main__': # 單進(jìn)程 start = time.time() coding('python') for i in range(5): print("main program", end=' | ') time.sleep(1) end = time.time() print('\nOne process cost time:', end - start) # 多進(jìn)程 multi_start = time.time() p = Process(target=coding, args=('python', )) p.start() for i in range(5): print("main program", end=' | ') time.sleep(1) multi_end = time.time() print('\nMulti process cost time:', multi_end - multi_start)
運(yùn)行結(jié)果:
python coding | python coding | python coding | python coding | python coding | main program | main program | main program | main program | main program |
One process cost time: 10.004231691360474
main program | python coding | main program | python coding | main program | python coding | main program | python coding | main program | python coding |
Multi process cost time: 5.082065582275391
multiprocessing模塊是跨平臺和版本的多進(jìn)程模塊,提供了一個(gè)Process類來創(chuàng)建進(jìn)程對象。創(chuàng)建子進(jìn)程時(shí),只需要傳入一個(gè)需要執(zhí)行的函數(shù)和函數(shù)的參數(shù),創(chuàng)建一個(gè)Process實(shí)例,用start()方法啟動(dòng)這個(gè)實(shí)例。
在上面的代碼中,定義了一個(gè)coding函數(shù),實(shí)現(xiàn)多進(jìn)程時(shí),實(shí)例化了一個(gè)Process類的對象p,p就是一個(gè)進(jìn)程對象,將需要執(zhí)行的函數(shù)傳給target參數(shù),將coding函數(shù)需要的參數(shù)以元組的形式傳給args參數(shù)(必須是一個(gè)元組),再用p對象的start()方法開啟了一個(gè)子進(jìn)程。
coding函數(shù)是一個(gè)需要執(zhí)行的任務(wù),在主進(jìn)程中需要執(zhí)行的代碼是另一個(gè)任務(wù),這時(shí)候有兩個(gè)任務(wù)。兩個(gè)任務(wù)都在主進(jìn)程中執(zhí)行時(shí),花了10秒多的時(shí)間,創(chuàng)建一個(gè)子進(jìn)程來執(zhí)行coding函數(shù)時(shí),花了5秒多的時(shí)間。創(chuàng)建子進(jìn)程之后,主進(jìn)程和子進(jìn)程同時(shí)處理任務(wù),這說明我們實(shí)現(xiàn)了多進(jìn)程處理多任務(wù),即多個(gè)任務(wù)是“同時(shí)”執(zhí)行的。
三、Process語法結(jié)構(gòu)和常用方法
Process([group [, target [, name [, args [, kwargs]]]]])
- 1.target:傳遞一個(gè)函數(shù)的引用,可以認(rèn)為這個(gè)子進(jìn)程就是執(zhí)行這個(gè)函數(shù)的代碼,這里傳的是函數(shù)的引用,后面不能有小括號
- 2.args:給target指定的函數(shù)傳遞的參數(shù),以元組的方式傳遞,這里必須是一個(gè)元組,如果不是元組會(huì)報(bào)TypeError,只有一個(gè)參數(shù)時(shí)要注意別出錯(cuò)
- 3.kwargs:給target指定的函數(shù)傳遞關(guān)鍵字參數(shù),以字典的方式傳遞,這里必須是一個(gè)字典
- 4.name:給進(jìn)程設(shè)定一個(gè)名字,可以不設(shè)定
- 5.group:指定進(jìn)程組,大多數(shù)情況下用不到
Process的常用方法:
- 1.start():啟動(dòng)子進(jìn)程實(shí)例(創(chuàng)建子進(jìn)程)
- 2.is_alive():判斷子進(jìn)程是否還在活著
- 3.join([timeout]):是否等待子進(jìn)程執(zhí)行結(jié)束,或等待多少秒
- 4.terminate():不管任務(wù)是否完成,立即終止子進(jìn)程
Process的常用屬性:
- 1.name:當(dāng)前進(jìn)程的別名,默認(rèn)為Process-N,N為從1開始遞增的整數(shù)
- 2.pid:當(dāng)前進(jìn)程的pid(進(jìn)程號)
獲取當(dāng)前進(jìn)程的id和當(dāng)前進(jìn)程的父進(jìn)程的id,需要使用os模塊:
- 1.os.getpid():獲取當(dāng)前進(jìn)程的id
- 2.os.getppid() :獲取當(dāng)前進(jìn)程的父進(jìn)程的id
四、進(jìn)程間不共享全局變量
from multiprocessing import Process import time str_list = ['ppp', 'yyy'] def add_str1(): """子進(jìn)程1""" print('In process one: ', str_list) for x in 'thon': str_list.append(x * 3) time.sleep(1) print('In process one: ', str_list) def add_str2(): """子進(jìn)程1""" print('In process two: ', str_list) for x in 'thon': str_list.append(x) time.sleep(1) print('In process two: ', str_list) if __name__ == '__main__': p1 = Process(target=add_str1) p1.start() p2 = Process(target=add_str2) p2.start()
運(yùn)行結(jié)果:
In process one: ['ppp', 'yyy']
In process two: ['ppp', 'yyy']
In process one: ['ppp', 'yyy', 'ttt']
In process two: ['ppp', 'yyy', 't']
In process one: ['ppp', 'yyy', 'ttt', 'hhh']
In process two: ['ppp', 'yyy', 't', 'h']
In process one: ['ppp', 'yyy', 'ttt', 'hhh', 'ooo']
In process two: ['ppp', 'yyy', 't', 'h', 'o']
In process one: ['ppp', 'yyy', 'ttt', 'hhh', 'ooo', 'nnn']
In process two: ['ppp', 'yyy', 't', 'h', 'o', 'n']
在上面的代碼中,str_list是一個(gè)全局變量,進(jìn)程p1和p2同時(shí)在使用str_list,都在往列表中添加元素,但是兩個(gè)進(jìn)程對列表的添加互不相關(guān)。
進(jìn)程p1與進(jìn)程p2不共享全局變量。
總結(jié)
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
Python機(jī)器學(xué)習(xí)入門(一)序章
這篇文章主要介紹了Python機(jī)器學(xué)習(xí)入門知識,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2021-08-08Python使用tarfile模塊實(shí)現(xiàn)免費(fèi)壓縮解壓
Python自帶的tarfile模塊可以方便讀取tar歸檔文件,厲害的是可以處理使用gzip和bz2壓縮歸檔文件tar.gz和tar.bz2,這篇文章主要介紹了Python使用tarfile模塊實(shí)現(xiàn)免費(fèi)壓縮解壓,需要的朋友可以參考下2024-03-03使用pyqt 實(shí)現(xiàn)重復(fù)打開多個(gè)相同界面
今天小編就為大家分享一篇使用pyqt 實(shí)現(xiàn)重復(fù)打開多個(gè)相同界面,具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧2019-12-12Linux RedHat下安裝Python2.7開發(fā)環(huán)境
這篇文章主要為大家詳細(xì)介紹了Linux RedHat下安裝Python2.7、pip、ipython環(huán)境、eclipse和PyDev環(huán)境,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-05-05python return邏輯判斷表達(dá)式實(shí)現(xiàn)解析
這篇文章主要介紹了python return邏輯判斷表達(dá)式實(shí)現(xiàn)解析,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2019-12-12Python連接MySQL并使用fetchall()方法過濾特殊字符
這篇文章主要介紹了Python連接MySQL的方法并講解了如何使用fetchall()方法過濾特殊字符,示例環(huán)境為Ubuntu操作系統(tǒng),需要的朋友可以參考下2016-03-03