Python使用multiprocessing實(shí)現(xiàn)多進(jìn)程
一、進(jìn)程概念
進(jìn)程(Process)是資源分配的最小單位,它是操作系統(tǒng)進(jìn)行資源分配和調(diào)度運(yùn)行的基本單位,通俗理解:一個(gè)正在運(yùn)行的程序就是一個(gè)進(jìn)程。
注: 一個(gè)程序運(yùn)行后至少有一個(gè)進(jìn)程
二、python多進(jìn)程
在python中使用多進(jìn)程我們需要導(dǎo)入 multiprocessing 模塊
import multiprocessing
實(shí)例演示:
- 我們先定義兩個(gè)函數(shù),然后創(chuàng)建子進(jìn)程去調(diào)用它們
import time
def mission1(n):
for i in range(1, n + 1):
print(f'第{i}次執(zhí)行任務(wù)一。')
time.sleep(0.2)
def mission2(n):
for i in range(1, n + 1):
print(f"第{i}次執(zhí)行任務(wù)二。")
time.sleep(0.2)
每個(gè)函數(shù)每次循環(huán)都sleep 0.2秒目的是為了之后演示進(jìn)程之間是同步執(zhí)行的情況,否則程序運(yùn)行太快沒辦法體現(xiàn)。
我們先試著直接調(diào)用它們:
mission1(5) mission2(5) """ 結(jié)果: 第1次執(zhí)行任務(wù)一。 第2次執(zhí)行任務(wù)一。 第3次執(zhí)行任務(wù)一。 第4次執(zhí)行任務(wù)一。 第5次執(zhí)行任務(wù)一。 第1次執(zhí)行任務(wù)二。 第2次執(zhí)行任務(wù)二。 第3次執(zhí)行任務(wù)二。 第4次執(zhí)行任務(wù)二。 第5次執(zhí)行任務(wù)二。 """
結(jié)果:先執(zhí)行了mission1 再執(zhí)行了mission2
- 子進(jìn)程依賴于父進(jìn)程創(chuàng)建,因而我們要?jiǎng)?chuàng)建兩個(gè)子進(jìn)程,那么必須在父進(jìn)程里面去創(chuàng)建。
python運(yùn)行文件的時(shí)候會(huì)創(chuàng)建一個(gè)主進(jìn)程也就是 MainProcess,因而我們必須在main里面去操作子進(jìn)程:
if __name__ == '__main__': pass
- 接著我們創(chuàng)建子進(jìn)程對(duì)象:
if __name__ == '__main__':
p1 = multiprocessing.Process(target=mission1, args=(5,))
p2 = multiprocessing.Process(target=mission2, kwargs={'n': 5})
multiprocessing.Process(group=None, target=None, name=None, args=(), kwargs={}) :
target—表示調(diào)用對(duì)象,即子進(jìn)程要執(zhí)行的任務(wù)(回調(diào)函數(shù)入口地址)
args—表示以元組的形式向子任務(wù)函數(shù)傳參,元組方式傳參一定要和參數(shù)的順序保持一致
kwargs—表示以字典的方式給子任務(wù)函數(shù)傳參,字典方式傳參字典中的key要和參數(shù)名保持一致
name—為子進(jìn)程的名稱
進(jìn)程運(yùn)行:
p1.start() p2.start()
- 完整代碼:
import multiprocessing
import time
def mission1(n):
for i in range(1, n + 1):
print(f'第{i}次執(zhí)行任務(wù)一。')
time.sleep(0.2)
def mission2(n):
for i in range(1, n + 1):
print(f"第{i}次執(zhí)行任務(wù)二。")
time.sleep(0.2)
if __name__ == '__main__':
p1 = multiprocessing.Process(target=mission1, args=(5,)) # 注意單元素的元組格式
p2 = multiprocessing.Process(target=mission2, kwargs={'n': 5})
p1.start()
p2.start()
"""
結(jié)果:
第1次執(zhí)行任務(wù)一。
第1次執(zhí)行任務(wù)二。
第2次執(zhí)行任務(wù)一。
第2次執(zhí)行任務(wù)二。
第3次執(zhí)行任務(wù)一。
第3次執(zhí)行任務(wù)二。
第4次執(zhí)行任務(wù)一。
第4次執(zhí)行任務(wù)二。
第5次執(zhí)行任務(wù)一。
第5次執(zhí)行任務(wù)二。
"""
結(jié)果顯示:兩個(gè)函數(shù)在兩個(gè)子進(jìn)程中同時(shí)執(zhí)行。(每次執(zhí)行順序可能有略微差別)
獲取進(jìn)程信息
current_process()
獲取當(dāng)前進(jìn)程的信息:name(進(jìn)程名稱) 和 pid (進(jìn)程ID)
def mission1(user, n):
print(f"mission-1子進(jìn)程:{multiprocessing.current_process().name}")
print(f"mission-1子進(jìn)程ID:{multiprocessing.current_process().pid}")
for i in range(1, n + 1):
print(f"用戶{user}正在第{i}次執(zhí)行任務(wù)一。")
time.sleep(0.2)
OS 模塊
可以使用os模塊中的getpid()獲取當(dāng)前進(jìn)程的ID 以及 getppid()獲取當(dāng)前進(jìn)程的父進(jìn)程ID。
import os
def mission2(user, n):
print(f"mission-2子進(jìn)程:{multiprocessing.current_process().name}")
print(f"mission-2子進(jìn)程ID:{os.getpid()}")
print(f"mission-2子進(jìn)程的父進(jìn)程為:{os.getppid()}")
for i in range(1, n + 1):
print(f"用戶{user}正在第{i}次執(zhí)行任務(wù)二。")
time.sleep(0.2)
完整代碼:
import multiprocessing
import time
import os
def mission1(user, n):
print(f"mission-1子進(jìn)程:{multiprocessing.current_process().name}")
print(f"mission-1子進(jìn)程ID:{multiprocessing.current_process().pid}")
print(f"mission-1子進(jìn)程的父進(jìn)程為:{os.getppid()}")
for i in range(1, n + 1):
print(f"用戶{user}正在第{i}次執(zhí)行任務(wù)一。")
time.sleep(0.2)
def mission2(user, n):
print(f"mission-2子進(jìn)程:{multiprocessing.current_process().name}")
print(f"mission-2子進(jìn)程ID:{os.getpid()}")
print(f"mission-2子進(jìn)程的父進(jìn)程為:{os.getppid()}")
for i in range(1, n + 1):
print(f"用戶{user}正在第{i}次執(zhí)行任務(wù)二。")
time.sleep(0.2)
if __name__ == '__main__':
print(f"主進(jìn)程的ID為:{multiprocessing.current_process().pid}")
print(f"主進(jìn)程的父進(jìn)程ID為:{os.getppid()}")
print(f'--------主進(jìn)程{multiprocessing.current_process().name}開始執(zhí)行--------')
p1=multiprocessing.Process(target=mission1,name='mission-1',args=('張三',5))
p2=multiprocessing.Process(target=mission2,name='mission-2',args=('李四',5))
p1.start()
p2.start()
"""
主進(jìn)程的ID為:7500
主進(jìn)程的父進(jìn)程ID為:39284
--------主進(jìn)程MainProcess開始執(zhí)行--------
mission-2子進(jìn)程:mission-2
mission-2子進(jìn)程ID:40552
mission-2子進(jìn)程的父進(jìn)程為:7500
用戶李四正在第1次執(zhí)行任務(wù)二。
mission-1子進(jìn)程:mission-1
mission-1子進(jìn)程ID:46296
mission-1子進(jìn)程的父進(jìn)程為:7500
用戶張三正在第1次執(zhí)行任務(wù)一。
用戶李四正在第2次執(zhí)行任務(wù)二。
用戶張三正在第2次執(zhí)行任務(wù)一。
用戶李四正在第3次執(zhí)行任務(wù)二。
用戶張三正在第3次執(zhí)行任務(wù)一。
用戶李四正在第4次執(zhí)行任務(wù)二。
用戶張三正在第4次執(zhí)行任務(wù)一。
用戶李四正在第5次執(zhí)行任務(wù)二。
用戶張三正在第5次執(zhí)行任務(wù)一。
"""
兩個(gè)子進(jìn)程的父ID是相同的就是MainProcess這個(gè)主進(jìn)程的ID
三、進(jìn)程特點(diǎn)
- 多進(jìn)程之間不會(huì)共享全局變量
- 主進(jìn)程會(huì)默認(rèn)等待子進(jìn)程結(jié)束而結(jié)束 但可以通過設(shè)置來讓子進(jìn)程跟著主進(jìn)程結(jié)束而結(jié)束
正常情況:
import multiprocessing
import time
def mission1(user, n):
for i in range(1, n + 1):
print(f"用戶{user}正在第{i}次執(zhí)行任務(wù)一。")
time.sleep(0.1)
if __name__ == '__main__':
print(f'--------主進(jìn)程{multiprocessing.current_process().name}開始執(zhí)行--------')
p1 = multiprocessing.Process(target=mission1, name='mission-1', args=('張三', 5))
p1.start()
time.sleep(0.4) # 讓主進(jìn)程多執(zhí)行一會(huì)兒
print(f'----------主進(jìn)程:{multiprocessing.current_process().name}最后一行代碼執(zhí)行完畢---------')
"""
--------主進(jìn)程MainProcess開始執(zhí)行--------
用戶張三正在第1次執(zhí)行任務(wù)一。
用戶張三正在第2次執(zhí)行任務(wù)一。
----------主進(jìn)程:MainProcess最后一行代碼執(zhí)行完畢---------
用戶張三正在第3次執(zhí)行任務(wù)一。
用戶張三正在第4次執(zhí)行任務(wù)一。
用戶張三正在第5次執(zhí)行任務(wù)一。
"""
正常情況下,主進(jìn)程(最后一行代碼執(zhí)行完了)仍然會(huì)等待子進(jìn)程(p1 mission-1)執(zhí)行完畢.
使用守護(hù)進(jìn)程或者終止進(jìn)程
import multiprocessing
import time
def mission1(user, n):
for i in range(1, n + 1):
print(f"用戶{user}正在第{i}次執(zhí)行任務(wù)一。")
time.sleep(0.1)
if __name__ == '__main__':
print(f'--------主進(jìn)程{multiprocessing.current_process().name}開始執(zhí)行--------')
p1 = multiprocessing.Process(target=mission1, name='mission-1', args=('張三', 5))
# 方式1: 開啟子進(jìn)程前提前設(shè)置守護(hù)主進(jìn)程
p1.daemon = True
p1.start()
time.sleep(0.4) # 讓主進(jìn)程多執(zhí)行一會(huì)兒
# p1.terminate()
print(f'----------主進(jìn)程:{multiprocessing.current_process().name}最后一行代碼執(zhí)行完畢---------')
"""
--------主進(jìn)程MainProcess開始執(zhí)行--------
用戶張三正在第1次執(zhí)行任務(wù)一。
用戶張三正在第2次執(zhí)行任務(wù)一。
----------主進(jìn)程:MainProcess最后一行代碼執(zhí)行完畢---------
"""
我們發(fā)現(xiàn)子進(jìn)程還沒執(zhí)行結(jié)束就被終止了。
- 多進(jìn)程之間是無序的
以上就是Python使用multiprocessing實(shí)現(xiàn)多進(jìn)程的詳細(xì)內(nèi)容,更多關(guān)于Python multiprocessing多線程的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
運(yùn)籌學(xué)-Python實(shí)現(xiàn)圖論與最短距離
需要求解任意兩個(gè)節(jié)點(diǎn)之間的最短距離,使用?Floyd?算法,只要求解單源最短路徑問題,有負(fù)權(quán)邊時(shí)使用?Bellman-Ford?算法,沒有負(fù)權(quán)邊時(shí)使用?Dijkstra?算法,本節(jié)我們只討論Dijkstra?算法,需要的朋友可以參考一下2022-01-01
python3中apply函數(shù)和lambda函數(shù)的使用詳解
本文主要介紹了python3中apply函數(shù)和lambda函數(shù)的使用詳解,文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-02-02
Python中實(shí)例化class的執(zhí)行順序示例詳解
這篇文章主要給大家介紹了關(guān)于Python中實(shí)例化class的執(zhí)行順序的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家學(xué)習(xí)或者使用python具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2018-10-10
Pytorch平均池化nn.AvgPool2d()使用方法實(shí)例
平均池化層,又叫平均匯聚層,下面這篇文章主要給大家介紹了關(guān)于Pytorch平均池化nn.AvgPool2d()使用方法的相關(guān)資料,文中通過實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下2023-02-02
對(duì)python修改xml文件的節(jié)點(diǎn)值方法詳解
今天小編就為大家分享一篇對(duì)python修改xml文件的節(jié)點(diǎn)值方法詳解,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2018-12-12
如何使用OpenCV實(shí)現(xiàn)手勢(shì)音量控制
今天來學(xué)習(xí)一下如何使用OpenCV實(shí)現(xiàn)手勢(shì)音量控制,本次實(shí)驗(yàn)需要使用OpenCV和mediapipe庫(kù)進(jìn)行手勢(shì)識(shí)別,并利用手勢(shì)距離控制電腦音量,感興趣的朋友跟隨小編一起看看吧2023-11-11
python如何通過注冊(cè)表動(dòng)態(tài)管理組件
使用注冊(cè)表的主要優(yōu)勢(shì)是可以在運(yùn)行時(shí)動(dòng)態(tài)創(chuàng)建對(duì)象,從而實(shí)現(xiàn)高度可配置和可擴(kuò)展的設(shè)計(jì),這篇文章主要介紹了python如何通過注冊(cè)表動(dòng)態(tài)管理組件,需要的朋友可以參考下2024-05-05

