以前咱們已經瞭解了不少進程相關的理論知識,瞭解進程是什麼應該再也不困難了,剛剛咱們已經瞭解了,運行中的程序就是一個進程。全部的進程都是經過它的父進程來建立的。所以,運行起來的python程序也是一個進程,那麼咱們也能夠在程序中再建立進程。多個進程能夠實現併發效果,也就是說,當咱們的程序中存在多個進程的時候,在某些時候,就會讓程序的執行速度變快。以咱們以前所學的知識,並不能實現建立進程這個功能,因此咱們就須要藉助python中強大的模塊。python
仔細說來,multiprocess不是一個模塊而是python中一個操做、管理進程的包。 之因此叫multi是取自multiple的多功能的意思,在這個包中幾乎包含了和進程有關的全部子模塊。因爲提供的子模塊很是多,爲了方便你們歸類記憶,我將這部分大體分爲四個部分:建立進程部分,進程同步部分,進程池部分,進程之間數據共享。linux
process模塊是一個建立進程的模塊,藉助這個模塊,就能夠完成進程的建立。windows
Process([group [, target [, name [, args [, kwargs]]]]])
,由該類實例化獲得的對象,表示一個子進程中的任務(還沒有啓動)安全
強調:網絡
參數介紹:併發
args=(1,2,'egon',)
kwargs={'name':'egon','age':18}
p.start()
:啓動進程,並調用該子進程中的p.run()p.run()
:進程啓動時運行的方法,正是它去調用target指定的函數,咱們自定義類的類中必定要實現該方法p.terminate()
:強制終止進程p,不會進行任何清理操做,若是p建立了子進程,該子進程就成了殭屍進程,使用該方法須要特別當心這種狀況。若是p還保存了一個鎖那麼也將不會被釋放,進而致使死鎖p.is_alive()
:若是p仍然運行,返回Truep.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
:進程的pidp.exitcode
:進程在運行時爲None、若是爲–N,表示被信號N結束(瞭解便可)p.authkey
:進程的身份驗證鍵,默認是由os.urandom()
隨機生成的32字符的字符串。這個鍵的用途是爲涉及網絡鏈接的底層進程間通訊提供安全性,這類鏈接只有在具備相同的身份驗證鍵時才能成功(瞭解便可)在Windows操做系統中因爲沒有fork(linux操做系統中建立進程的機制),在建立子進程的時候會自動 import 啓動它的這個文件,而在 import 的時候又執行了整個文件。所以若是將process()直接寫在文件中就會無限遞歸建立子進程報錯。因此必須把建立子進程的部分使用if __name__ =='__main__'
判斷保護起來,import 的時候,就不會遞歸運行了。app
在一個python進程中開啓子進程,start方法和併發效果。dom
# 沒有參數的,開啓單個子進程 from multiprocessing import Process import time def talk(): print('開啓子進程start') time.sleep(1) print('結束子進程end') if __name__ == '__main__': p = Process(target=talk) p.start() # 告訴操做系統,我要開啓子進程,僅僅是開啓子進程就完了,接着走下面的代碼,具體操做系統何時開是操做系統的事情 print('主進程/父進程')
主進程/父進程
開啓子進程start
結束子進程endsocket
# 帶有參數的,開啓多個子進程 def talk(name): print(f'{name}子進程start') time.sleep(1) print(f'{name}子進程end') if __name__ == '__main__': p = Process(target=talk,args=('xichen',)) p1 = Process(target=talk,args = ('nick',)) p.start() p1.start() print('主進程/父進程')
主進程/父進程
xichen子進程start
nick子進程start
xichen子進程end
nick子進程end函數
注意:開啓多個進程的時候,操做系統先開啓哪個進程是咱們控制不了的,這是操做系統本身所擁有的調度機制
class Test(Process): def __init__(self,name): super().__init__() self.name = name def run(self): print(f'子進程{self.name}-->start') time.sleep(1) print(f'子進程{self.name}-->end') if __name__ == '__main__': p = Test('xichen') p1 = Test('nick') p.start() # 向操做系統發送開啓子進程,這個時候會自動觸發Test類的run方法 p1.start() print('主進程/子進程')
主進程/子進程
子進程xichen-->start
子進程nick-->start
子進程xichen-->end
子進程nick-->end
def f1(): print('子進程start') time.sleep(2) print('子進程end') if __name__ == '__main__': print('開始父進程') p = Process(target=f1) p.start() p.join() # 是父進程要等待子進程結束後,再啓動父進程 # time.sleep(5) 其實核心其實就是在啓動主進程的以前加一個延時,讓他等子進程結束後再執行 print('我是父進程,等待子進程運行結束再結束')
開始父進程
子進程start
子進程end
我是父進程,等待子進程運行結束再結束
1.join方法實現多個子進程並行結束後,在結束父進程 from multiprocessing import Process import time def f(i): print(f'進程{i} start') time.sleep(i) print(f'進程{i} end') if __name__ == '__main__': print('開始父進程') p1 = Process(target=f,args=(1,)) p2 = Process(target=f,args=(2,)) p3 = Process(target=f,args=(3,)) start = time.time() p1.start() p2.start() p3.start() # join核心就是將程序堵塞在這裏,主進程須要等待子進程結束之後,在去執行 p1.join() p2.join() p3.join() end = time.time() # 總時長:按照最長的時間計算多一點 print('程序執行的時間:',end - start) # 3s多,由於執行的進程是在一個時間的 print('啓動父進程')
開始父進程
進程1 start
進程2 start
進程3 start
進程1 end
進程2 end
進程3 end
程序執行的時間: 3.5759353637695312
啓動父進程
2.join方法實現多個子進程串行結束後,在結束父進程 # 用Process類來建立多個子進程,而且用join方法讓父進程等待着子進程結束之後,在結束父進程 # 可是這樣太耗費時間了,還不如直接調用咱們寫的函數實現 # 1.實現多個進程串行結束之後,在結束掉父進程 def f(i): print(f'子進程{i} start') time.sleep(i) print(f'子進程{i} end') if __name__ == '__main__': print('開始父進程') p1 = Process(target=f,args=(1,)) p2 = Process(target=f,args=(2,)) p3 = Process(target=f,args=(3,)) start = time.time() p1.start() p1.join() p2.start() p2.join() p3.start() p3.join() end = time.time() print('程序執行的總時長:',end-start) # 7s多, print('結束父進程') # 2.直接利用函數調用的方法來實現多個子進程串行的結束 # def f1(i): # print(f'子進程{i} start') # time.sleep(i) # print(f'子進程{i} end') # # if __name__ == '__main__': # print('開啓主進程') # start = time.time() # f1(1) # f1(2) # f1(3) # end = time.time() # print('程序執行的總時間:',end - start) # 6秒多, # print('結束父進程') 開啓主進程 子進程1 start 子進程1 end 子進程2 start 子進程2 end 子進程3 start 子進程3 end 程序執行的總時間: 6.001583814620972 結束父進程
開始父進程
子進程1 start
子進程1 end
子進程2 start
子進程2 end
子進程3 start
子進程3 end
程序執行的總時長: 7.081932783126831
結束父進程
3.優化join實現多個子進程並行結束後,結束父進程 # 對join實現多個子進程並行結束在結束主進程,作了優化, # 咱們不用在建立多個子進程的時候,每次用Process類來實例化一個新的進程對象 # 能夠直接使用循環,這樣更方便簡潔一些 def f(i): print(f'子進程{i} start') time.sleep(i) print(f'子進程{i} end') if __name__ == '__main__': print('開始執行主進程') p_lst = [] start = time.time() for i in range(1,4): p = Process(target=f,args=(i,)) p_lst.append(p) p.start() for p in p_lst: p.join() end = time.time() print('結束主進程') print('程序執行的總時長:',end-start)
開始執行主進程
子進程2 start
子進程1 start
子進程3 start
子進程1 end
子進程2 end
子進程3 end
結束主進程
程序執行的總時長: 3.49997878074646
from multiprocessing import Process import os,time def f(i): print(f'子進程{i} start') print('在子進程中查看本身的進程號pid:',os.getpid(),'在子進程中查看父進程的進程號pid:',os.getppid()) time.sleep(i) print(f'子進程{i} end') if __name__ == '__main__': print('開始父進程') p = Process(target=f,args=(1,)) p.start() p.join() print('在父進程中查看子進程的進程號pid:',p.pid,'在父進程中查看主進程進程號:',os.getpid() ,'在父進程中查看父進程的父進程號pid:',os.getppid()) print('結束父進程')
開始父進程
子進程1 start
在子進程中查看本身的進程號pid: 15352 在子進程中查看父進程的進程號pid: 12416
子進程1 end
在父進程中查看子進程的進程號pid: 15352 在父進程中查看主進程進程號: 12416 在父進程中查看父進程的父進程號pid: 12248
結束父進程
from multiprocessing import Process import os import time # 1.terminate 方法 def f(i): print(f'子進程{i} start') time.sleep(i) print(f'子進程{i} end') if __name__ == '__main__': print('開始執行父進程') p = Process(target=f,args=(1,)) p.start() p.terminate() # 用來關閉打開的子進程,可是他不會立馬關閉,因此is_alive查看進程存活狀態的時候,不必定是已經死了 print(p.is_alive()) p.join() print(p.is_alive()) print('結束父進程')
開始執行父進程
True
False
結束父進程
import time from multiprocessing import Process,current_process def f(i): print(f'子進程{i} start') print(f'當前進程{i}的名字爲:',current_process().name) print(f'當前進程{i}的進程號爲:',current_process().pid) print(f'子進程{i} end') if __name__ == '__main__': print('開始執行父進程') p1 = Process(target=f,args=(1,)) p2 = Process(target=f,args=(2,)) p3 = Process(target=f,args=(3,)) p1.start() p1.join() p2.start() p2.join() p3.start() p3.join() print('結束父進程')
開始執行父進程
子進程1 start
當前進程1的名字爲: Process-1
當前進程1的進程號爲: 6232
子進程1 end
子進程2 start
當前進程2的名字爲: Process-2
當前進程2的進程號爲: 14552
子進程2 end
子進程3 start
當前進程3的名字爲: Process-3
當前進程3的進程號爲: 12896
子進程3 end
結束父進程
from multiprocessing import Process class Mydata(Process): def __init__(self,name): # self.name = name # 這裏的name屬性是Process類的name屬性,表示的是當前進程的名字,打印進程的名字的時候 # 打印的並非咱們須要的實例化進程時給的初始值 開始執行父進程 子進程Mydata-1 start 子進程Mydata-1 start 結束父進程 super().__init__() # 在這裏執行父類Process的__init__方法的時候,process裏的init方法由會將name屬性的值給覆蓋掉 self.name = name # 若是不想要覆蓋掉咱們的name屬性值的話,咱們須要在super()後面對進程對象的name屬性值賦值 def run(self): print(f'子進程{self.name} start') print(f'子進程{self.name} start') if __name__ == '__main__': print('開始執行父進程') p = Mydata('xichen') p.start() p.join() print('結束父進程')
開始執行父進程
子進程xichen start
子進程xichen start
結束父進程
from multiprocessing import Process import time def foo(i): print(f'守護進程{i} start') time.sleep(2) print(f'守護進程{i} end') def fo(i): print(f'子進進程{i} start') time.sleep(2) print(f'子進進程{i} end') if __name__ == '__main__': print('開始執行父進程') p = Process(target=foo,args=(1,)) p1 = Process(target=fo,args=(2,)) p.daemon = True # 把這個子進程定義爲了守護進程 # 它不會影響p2這個進程對象的執行 p.start() p1.start() time.sleep(1) print('父進程結束')
開始執行父進程
子進進程2 start
守護進程1 start
父進程結束
子進進程2 end
# Author:xichen # @Time:2019/9/1114:24 import socket from multiprocessing import Process server = socket.socket(socket.AF_INET,socket.SOCK_STREAM) server.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1) server.bind(('192.168.11.78',8002)) server.listen(10) def Mydata(conn,client_addr): while True: try: data = conn.recv(1024) if not data: conn.close() break print('子進程的數據爲:',data) conn.send(data.upper()) print('向子進程發送的數據爲:',data.upper().decode('utf8')) except Exception: break if __name__ == '__main__': while True: conn,client_addr = server.accept() print(f'開啓子進程:地址爲:{client_addr}') p = Process(target = Mydata,args=(conn,client_addr)) p.start()
import socket client = socket.socket() client.connect(('192.168.11.78',8002)) while True: data = input('開始發送數據:') if not data: break client.send(data.encode('utf8')) msg = client.recv(1024) print('接收服務端返回
進程之間的數據隔離問題
rom multiprocessing import Process import time x = 0 def task(): global x x = 100 print('子進程的x修改成了{}'.format(x)) if __name__ == '__main__': p = Process(target=task) p.start() time.sleep(5) print(x)
子進程的x修改成了100
0