一 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__':下
創建並開啟子進程的方式一
from multiprocessing import Process
import time
def task(name):
print("%s is running" % name)
time.sleep(3) # 模擬任務運行一段時間
print("%s is done" % name)
if __name__ == "__main__": # windows 一定要把開啟指令放到main下面 Linux無所謂
# Process(target=task, kargs={"name" : "子進程"}) # 方式1
p = Process(target=task, args=("子進程1",)) # 方式2 實例化得到一個對象
p.start() # (僅僅只是給操作系統發送了一個信號)開啟子進程,幫你執行task
print("主")
創建並開啟子進程的方式二
from multiprocessing import Process
import time
class MyProcess(Process):
def __init__(self,name):
super().__init__()
self.name = name
def run(self): # 一定是run
print("%s is running" % self.name)
time.sleep(3) # 模擬任務運行一段時間
print("%s is done" % self.name)
if __name__ == "__main__":
p = MyProcess("子進程1")
p.start() # 調用run
print("主")
四 練習題
1、思考開啟進程的方式一和方式二各開啟了幾個進程?
兩個進程
2、進程之間的內存空間是共享的還是隔離的?下述代碼的執行結果是什么?
from multiprocessing import Process
n=100 #在windows系統中應該把全局變量定義在if __name__ == '__main__'之上就可以了
def work():
global n
n=0
print('子進程內: ',n)
if __name__ == '__main__':
p=Process(target=work)
p.start()
print('主進程內: ',n)
進程之間的內存空間是隔離的
主進程內: 100 子進程內: 0
3、基於多進程實現並發的套接字通信?
server
import socket
from multiprocessing import Process
def talk(conn):
while True:
try:
data = conn.recv(1024)
if not data:
break
conn.send(data.upper())
except ConnectionRefusedError:
break
conn.close()
def server(ip, port):
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.setsockopt(socket.SOL_SOCKET, socket.SOL_REUSEARDOR, 1)
server.bind((ip, port))
server.listen(5)
while True:
conn, addr = server.accept()
p = Process(target=talk, args=(conn, ))
p.start()
server.close()
if __name__ == "__main__":
server("127.0.0.1", 8080)
client
import socket
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect(("127.0.0.1", 8080))
while True:
msg = input(">>:").strip()
if not msg:
break
client.send(msg.encode("utf-8"))
data = client.recv(1024)
print(data.decode("utf-8"))
一個程序運行一次是一個進程(結果),運行兩次是兩個進程
4、思考每來一個客戶端,服務端就開啟一個新的進程來服務它,這種實現方式有無問題?
來一個客戶端啟動一個進程,啟動一個進程,服務端內存是有限的,控制不了客戶端的數量。
