標籤:之間 通訊 child bar 對象 san 進程終止 停止 死結
multiprocessing模組介紹
python中的多線程無法利用多核優勢,如果想要充分地使用多核CPU的資源(os.cpu_count()查看),在python中大部分情況需要使用多進程。Python提供了multiprocessing。
multiprocessing模組用來開啟子進程,並在子進程中執行我們定製的任務(比如函數),該模組與多線程模組threading的編程介面類似。
multiprocessing模組的功能眾多:支援子進程、通訊和共用資料、執行不同形式的同步,提供了Process、Queue、Pipe、Lock等組件。
需要再次強調的一點是:與線程不同,進程沒有任何共用狀態,進程修改的資料,改動僅限於該進程內。
Process類的介紹
建立進程的類:
Process([group [, target [, name [, args [, kwargs]]]]]),由該類執行個體化得到的對象,
表示一個子進程中的任務(尚未啟動)
強調:
1. 需要使用關鍵字的方式來指定參數
2. args指定的為傳給target函數的位置參數,是一個元組形式,必須有逗號
參數介紹:
group參數未使用,值始終為None
target表示調用對象,即子進程要執行的任務
args表示調用對象的位置參數元組,args=(1,2,‘egon‘,)
kwargs表示調用對象的字典,kwargs={‘name‘:‘egon‘,‘age‘:18}
name為子進程的名稱
方法介紹:
p.start():啟動進程,並調用該子進程中的p.run()
p.run():進程啟動時啟動並執行方法,正是它去調用target指定的函數,我們自訂類
的類中一定要實現該方法
p.terminate():強制終止進程p,不會進行任何清理操作,如果p建立了子進程,
該子進程就成了殭屍進程,使用該方法需要特別小心這種情況。如果p還儲存了一
個鎖那麼也將不會被釋放,進而導致死結
p.is_alive():如果p仍然運行,返回True
p.join([timeout]):主線程等待p終止(強調:是主線程處於等的狀態,
而p是處於啟動並執行狀態)。timeout是可選的逾時時間,需要強調的是,p.join只能
join住start開啟的進程,而不能join住run開啟的進程
屬性介紹:
p.daemon:預設值為False,如果設為True,代表p為後台啟動並執行守護進程,當p的
父進程終止時,p也隨之終止,並且設定為True後,p不能建立自己的新進程,
必須在p.start()之前設定
p.name:進程的名稱
p.pid:進程的pid
p.exitcode:進程在運行時為None、如果為–N,表示被訊號N結束(瞭解即可)
p.authkey:進程的身分識別驗證鍵,預設是由os.urandom()隨機產生的32字元的字串。
這個鍵的用途是為涉及網路連接的底層處理序間通訊提供安全性,這類串連只有在具有
相同的身分識別驗證鍵時才能成功(瞭解即可)
Process類的使用
注意:在windows中Process()必須放到# if __name__ == ‘__main__‘:下
建立並開啟子進程的兩種方式
#開進程的方法一:
import time
import random
from multiprocessing import Process
def piao(name):
print(‘%s piaoing‘ %name)
time.sleep(random.randrange(1,5))
print(‘%s piao end‘ %name)
p1=Process(target=piao,args=(‘zhangsan‘,)) #必須加,號
p2=Process(target=piao,args=(‘lisi‘,))
p3=Process(target=piao,args=(‘wangwu‘,))
p4=Process(target=piao,args=(‘zhaoliu‘,))
p1.start()
p2.start()
p3.start()
p4.start()
print(‘主線程‘)
#開進程的方法二:
import time
import random
from multiprocessing import Process
class Piao(Process):
def __init__(self,name):
super().__init__()
self.name=name
def run(self):
print(‘%s piaoing‘ %self.name)
time.sleep(random.randrange(1,5))
print(‘%s piao end‘ %self.name)
p1=Piao(‘zhangsan‘)
p2=Piao(‘lisi‘)
p3=Piao(‘wangwu‘)
p4=Piao(‘zhaoliu‘)
p1.start() #start會自動調用run
p2.start()
p3.start()
p4.start()
print(‘主線程‘)
Process對象的join方法
主進程等,等待子進程結束
from multiprocessing import Process
import time
import random
class Piao(Process):
def __init__(self,name):
self.name=name
super().__init__()
def run(self):
print(‘%s is piaoing‘ %self.name)
time.sleep(random.randrange(1,3))
print(‘%s is piao end‘ %self.name)
p=Piao(‘zangsan‘)
p.start()
p.join(0.0001) #等待p停止,等0.0001秒就不再等了
print(‘開始‘)
有了join,程式不就是串列了嗎???
from multiprocessing import Process
import time
import random
def piao(name):
print(‘%s is piaoing‘ %name)
time.sleep(random.randint(1,3))
print(‘%s is piao end‘ %name)
p1=Process(target=piao,args=(‘zhangsan‘,))
p2=Process(target=piao,args=(‘lisi‘,))
p3=Process(target=piao,args=(‘wangwu‘,))
p4=Process(target=piao,args=(‘zhaoliu‘,))
p1.start()
p2.start()
p3.start()
p4.start()
#有的同學會有疑問:既然join是等待進程結束,那麼我像下面這樣寫,進程不就又變成串列的了嗎?
#當然不是了,必須明確:p.join()是讓誰等?
#很明顯p.join()是讓主線程等待p的結束,卡住的是主線程而絕非進程p,
#詳細解析如下:
#進程只要start就會在開始運行了,所以p1-p4.start()時,系統中已經有四個並發的進程了
#而我們p1.join()是在等p1結束,沒錯p1隻要不結束主線程就會一直卡在原地,這也是問題的關鍵
#join是讓主線程等,而p1-p4仍然是並發執行的,p1.join的時候,其餘p2,p3,p4仍然在運行,等#p1.join結束,可能p2,p3,p4早已經結束了,這樣p2.join,p3.join.p4.join直接通過檢測,無需等待
# 所以4個join花費的總時間仍然是耗費時間最長的那個進程啟動並執行時間
p1.join()
p2.join()
p3.join()
p4.join()
print(‘主線程‘)
#上述啟動進程與join進程可以簡寫為
# p_l=[p1,p2,p3,p4]
#
# for p in p_l:
# p.start()
#
# for p in p_l:
# p.join()
name與pid
from multiprocessing import Process
import time
import random
class Piao(Process):
def __init__(self,name):
# self.name=name
# super().__init__() #Process的__init__方法會執行self.name=Piao-1,
# #所以加到這裡,會覆蓋我們的self.name=name
#為我們開啟的進程設定名字的做法
super().__init__()
self.name=name
def run(self):
print(‘%s is piaoing‘ %self.name)
time.sleep(random.randrange(1,3))
print(‘%s is piao end‘ %self.name)
p=Piao(‘zhangsan‘)
p.start()
print(‘開始‘)
print(p.pid) #查看pid
守護進程
主進程建立守護進程
其一:守護進程會在主進程代碼執行結束後就終止
其二:守護進程內無法再開啟子進程,否則拋出異常:AssertionError: daemonic processes are not allowed to have children
注意:進程之間是互相獨立的,主進程代碼運行結束,守護進程隨即終止
from multiprocessing import Process
import time
import random
class Piao(Process):
def __init__(self,name):
self.name=name
super().__init__()
def run(self):
print(‘%s is piaoing‘ %self.name)
time.sleep(random.randrange(1,3))
print(‘%s is piao end‘ %self.name)
p=Piao(‘zhangsan‘)
p.daemon=True #一定要在p.start()前設定,設定p為守護進程,禁止p建立子進程,並且父進程代碼執行結束,p即終止運行
p.start()
print(‘主‘)
#主進程代碼運行完畢,守護進程就會結束,迷惑人的例子
from multiprocessing import Process
from threading import Thread
import time
def foo():
print(123)
time.sleep(1)
print("end123")
def bar():
print(456)
time.sleep(3)
print("end456")
p1=Process(target=foo)
p2=Process(target=bar)
p1.daemon=True
p1.start()
p2.start()
print("main-------") #列印該行則主進程代碼結束,則守護進程p1應該被終止,可能會有p1任務執行的列印資訊123,因為主進程列印main----時,p1也執行了,但是隨即被終止
識別圖中二維碼,歡迎關注python寶典
python多進程編程(一)