1. 程式人生 > >開啟進程的兩種方式

開啟進程的兩種方式

glob als 強制 並且 進程 啟動 aps pri 我們

一 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.daemon:默認值為False,如果設為True,代表p為後臺運行的守護進程,當p的父進程終止時,p也隨之終止,並且設定為True後,p不能創建自己的新進程,必須在p.start()之前設置

p.name:進程的名稱

p.pid:進程的pid

三 Process類的使用

註意:在windows中Process()必須放到# if __name__ == ‘__main__‘:下

創建並開啟子進程的方式一

技術分享圖片
 1 from multiprocessing import Process
 2 import time
 3 
 4 def task(name):
 5     print("%s is running" % name)
 6     time.sleep(3)
 7     print("%s is done" % name)
 8 
 9 
10 if __name__ == "__main__":
11     p = Process(target=task, kwargs={"name": "子進程1"})
12     p.start()
13     print("")
View Code

創建並開啟子進程的方式二

技術分享圖片
 1 from multiprocessing import Process
 2 import time
 3 
 4 class MyProcess(Process):
 5     def __init__(self, name):
 6         super().__init__()
 7         self.name = name
 8 
 9     def run(self):
10         """
11         默認方法run
12         :return:
13         """
14         print("%s is running" % self.name)
15         time.sleep(3)
16         print("%s is done " % self.name)
17         
18         
19 if __name__ == "__main__":
20     p = MyProcess("子進層1")
21     p.start()
View Code

四 練習題

1、思考開啟進程的方式一和方式二各開啟了幾個進程?

答:各開啟了兩進程

2、進程之間的內存空間是共享的還是隔離的?下述代碼的執行結果是什麽?

技術分享圖片
 1 from multiprocessing import Process
 2 
 3 #在windows系統中應該把全局變量定義在if __name__ == ‘__main__‘之上就可以了
 4 n=100 
 5 
 6 def work():
 7     global n
 8     n=0
 9     print(子進程內: ,n)
10 
11 
12 if __name__ == __main__:
13     p=Process(target=work)
14     p.start()
15     print(主進程內: ,n)
View Code

答:內存空間是隔離的。

代碼運行結果:

主進程內: 100
子進程內: 0

3、基於多進程實現並發的套接字通信?

服務端:

技術分享圖片
 1 import socket
 2 from multiprocessing import Process
 3 def talk(conn):
 4     while True:
 5         try:
 6             res = conn.recv(1024)
 7             if not res:
 8                 continue
 9             conn.send(res.upper())
10         except Exception as e:
11             print(\033[1;31m客戶端出現錯誤,關閉連接!---->\033[0m, e)
12             break
13     conn.close()
14 
15 def serve(ip, port):
16     server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
17     server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
18     server.bind((ip, port))
19     server.listen(5)
20 
21     while True:
22         conn, client_addr = server.accept()
23         p = Process(target=talk, args=(conn,))
24         p.start()
25 
26 
27 if __name__ == "__main__":
28     serve("127.0.0.1", 8080)
View Code

客戶端:

技術分享圖片
 1 import socket
 2 
 3 client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
 4 
 5 client.connect(("127.0.0.1", 8080))
 6 while True:
 7     cmd = input(">>>:").strip()
 8     if not cmd:continue
 9     client.send(cmd.encode("utf-8"))
10     res = client.recv(1024)
11     print(res.decode("utf-8"))
View Code

思考每來一個客戶端,服務端就開啟一個新的進程來服務它,這種實現方式有無問題?

答:有問題,如果客戶端越來越多,多道一定的數目,服務端會奔潰:

開啟進程的兩種方式