python多進程編程(一)

來源:互聯網
上載者:User

標籤:之間   通訊   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多進程編程(一)

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.