1、如何獲取進程的id號和進程的名字.安全
os.getpid() #獲取本進程的id號併發
os.getppid() #獲取本進程的父進程的id號app
import os from multiprocessing import Process def f1(): print('f1進程的pid',os.getpid()) print('f1進程的父進程的pid',os.getppid()) if __name__ == '__main__': p1 = Process(target=f1,name='歡迎') p1.start() print(p1.name) print('p1進程的pid',p1.pid) print('本進程的id',os.getpid()) # p1.pid #返回結果爲p1進程的id號 # os.getpid()#返回本進程的id號 # os.getppid()#返回爲本進程的父進程id號 # p1.name()#返回p1進程的名字
2、如何手動結束子進程,以及判斷子進程是否還在運行ui
obj.is_terminate() #給操做系統發送結束進程的信號spa
obj.is_alive() #判斷進程是否在運行,返回值True,False操作系統
import time from multiprocessing import Process def f1(): print('子進程1號') if __name__ == '__main__': p = Process(target=f1,) p.start() print(p.is_alive()) #判斷子進程是否還活着,是否還在運行 p.terminate() #給操做系統發送一個結束進程的信號 time.sleep(0.5) #須要延遲一會再判斷是否還存活,由於系統結束進程須要處理不少東西 print(p.is_alive())
3、如何驗證進程存在空間隔離code
對於打印結果的解釋:首先程序自上往下走,先打印一遍100,開啓子進程後,系統copy一份代碼走,並運行,又打印一遍100,子進程修改的只是本身進程裏的全局變量,對象
而父進程的變量仍是那個,這就驗證了進程之間存在空間隔離.blog
from multiprocessing import Process num = 100 def f1(): global num num = 3 #修改全局變量的值 print('f1進程中的num',num) print('>>>>>',num) if __name__ == '__main__': p = Process(target=f1,) p.start() p.join() print('主進程中的num',num) 打印結果爲: >>>>> 100 >>>>> 100 f1進程中的num 3 主進程中的num 100
4、關於守護進程隊列
obj(進程的實例化對象).daemon = True #開啓守護進程,必定要在開啓進程( obj.start() )前設置 什麼是守護進程: 1.在主進程代碼執行結束後就終止(應用場景:子進程須要跟父進程一塊兒結束時) 2.守護進程內沒法開啓子進程,不然拋異常
from multiprocessing import Process def f1(): print("xxx") def f2(): print("p普通子進車") if __name__ == '__main__': p = Process(target = f1,) p.daemon = True #開啓守護進程,必定要在開啓該進程(p.start())前設置,父進程代碼執行結束,這個守護進程也結束. p.start() #p.join() #給主進程阻塞,守護進程有機會執行裏面的代碼 print("主進程結束.") p2 = Process(target = f2,) #普通進程不受限制 p2.start()
5、關於殭屍進程和孤兒進程概念
殭屍進程:在子進程執行完,而主進程尚未執行完的時候,系統會保留執行的子進程一些信息(id號,名字...),它會隨着主進程的結束而被清理掉
孤兒進程:主進程在子進程前結束了,這個時候該子進程的一些信息沒人管了,就叫孤兒進程,最後會被系統清理.
6、關於互斥鎖\進程鎖\同步鎖:
什麼時進程所\互斥鎖\同步鎖: 控制進程在共享一個文件,或同一個打印終端的時候,產生競爭時的錯亂.原理是把併發改爲串行 with obj(鎖的實例化對象): #簡易寫法 須要上鎖的代碼 Lock.acquire() #加鎖 Lock.release() #解鎖
from multiprocessing import Process,Lock import time def show_t(i): with open("ticket","r",encoding = "utf-8")as f: #用with open打開文件,前2個能夠用位置參數,但第三個必須用關鍵字傳參 ticket_data = f.read() t_data = eval(ticket_data) print("%s查詢剩餘票數爲%s"%(i,t_data["count"])) def get_t(i,l1): # l1.acquire()#加鎖 with l1: #用了該枷鎖方法,就不用手動解鎖了 with open("ticket","r",encoding="utf-8")as f: ticket_data = f.read() #ticket票 data數據 t_data = eval(ticket_data) if t_data["count"]>0: t_data["count"]-=1 print("%s搶票成功"%i) time.sleep(0.2) with open("ticket","w")as f: f.write(str(t_data)) else: print("沒有票了") # l1.release() #解鎖 if __name__ == '__main__': l1 = Lock() for i in range(10): p1 = Process(target=show_t,args=(i,)) p1.start() for i in range(10): p2=Process(target=get_t,args=(i,l1)) #傳兩個參數要加括號 p2.start()
7、關於multiprocessing包的Queue模塊的使用
方法介紹: obj.put() #往隊列裏面放數據,若是隊列裏面滿了,會阻塞 obj.put_nowait() #滿了就報錯(不會阻塞程序,能夠經過捕獲異常來進行其餘的操做) obj.get() #從隊列裏面取數據,若是隊列裏面空了,會阻塞(等待) obj.get_nowait() #空了就報錯(不會阻塞程序,能夠經過捕獲異常來進行其餘的操做) obj.full() #查看隊列是否滿了,滿了返回True,但該命令的執行速度比put和get的速度快,因此結果不許確 obj.empty() #查看隊列是否空了,空了返回True,結果同理,有時不許確 obj.qsize() #返回當前隊列內容的長度,結果也不許確
舉例:關於Queue
from multiprocessing import Process,Queue def f1(q): q.put('約嗎?') if __name__ == '__main__': q = Queue(3) p = Process(target=f1,args=(q,)) p.start() #開啓子進程 son_p_msg = q.get() #從隊列裏面拿數據,隊列爲空,則阻塞等待 print('來自子進程的消息:',son_p_msg)
8、JoinableQueue方法(跟Queue相近)
JoinableQueue的實例p除了與Queue對象相同的方法以外還具備:
方法介紹:
q.task_done():使用者使用此方法發出信號,表示q.get()的返回項目已經被處理。若是調用此方法的次數大於從隊列中刪除項目的數量,將引起ValueError異常
下面例子中,應用此方法目的,是爲了解決,當有多個消費者程序,去隊列裏拿數據的時候,不知道隊列裏是否空了,而此方法,會往隊列裏面放入一個信號,表示該數據被拿走了.
q.join():生產者調用此方法進行阻塞,直到隊列中全部的項目均被處理。阻塞將持續到隊列中的每一個項目均調用q.task_done()方法爲止
import time from multiprocessing import Process,Queue,JoinableQueue #生產者 def producer(q): for i in range(10): time.sleep(0.2) s = '大包子%s號'%i print(s+'新鮮出爐,拿去用') q.put(s) q.join() #等待的是隊列的內容處理完畢(q是隊列的實例化對象),而不是等待上面代碼執行,就等着task_done()信號的數量,和我put進去的數量相同時,才繼續執行下面代碼
print('全部的任務都被處理了,繼續潛行吧騷年們')
#消費者 def consumer(q): while 1: time.sleep(0.5) baozi = q.get() print(baozi+'被吃了') q.task_done() #給隊列發送一個取出的這個任務已經處理完畢的信號 if __name__ == '__main__': # q = Queue(30) q = JoinableQueue(30) #一樣是一個長度爲30的隊列 pro_p = Process(target=producer,args=(q,)) con_p = Process(target=consumer,args=(q,)) pro_p.start() con_p.daemon = True #開啓守護進程,消費者會隨着主進程的結束而終結 con_p.start() pro_p.join() #讓主進程等待(生產者)子進程 print('主進程結束')
9、Manager方法
什麼是Manager方法:
Manager是是一種數據共享的方法.一種較爲高級的多進程通訊方式
進程之間的通訊:隊列、管道、數據共享(Manager).
隊列,管道,這些方式只適用於多個進程都是源於同一個父進程的狀況。若是多個進程不是源於同一個父進程,只能用共享內存,信號量等方式,還有就是數據共享(Manager)
多進程共同去處理共享數據的時候,就和咱們多進程同時去操做一個文件中的數據是同樣的,不加鎖就會出現錯誤的結果,進程不安全的,因此也須要加鎖
import time from multiprocessing import Process,Manager,Lock #建立進程的方法\數據共享的方法\互斥鎖方法 def f1(m_d,l2): with l2: tmp = m_d["num"] tmp -= 1 time.sleep(0.1) m_d["num"]=tmp if __name__ == '__main__': m = Manager() #實例化數據共享的對象 l2 = Lock #實例化鎖的對象 m_d = m.dict({"num":100}) p_list = [] for i in range(10): p = Process(target=f1,args=(m_d,l2)) p.start() p_list.append(p) [pp.join() for pp in p_list] print(m_d["num"])