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