在Python中如果想建立多程式需要用到multiprrocessing中的Prrocess方法。
在程式之間全域性變數是不共享的,如果要對程式的全域性變數進行使用的話就需要用到multiprrocessing的Queue方法
首先我們先建立一個多程式
import time from multiprocessing import Process # 程式之間全域性變數不共享 def work_1(): for i in range(10): print('任務1') time.sleep(0.5) def work_2(): for i in range(10): print('任務2') time.sleep(0.5) # 程式執行的時候不加main 為什麼會報錯: # 在執行過程中相當於在另外一個py檔案中匯入這個模組並執行函式,由於是匯入模組所以 # 建立多程式的程式碼也會被匯入,然後就又去開了執行緒,陷入無限遞迴的狀態 if __name__ == '__main__': # 建立兩個程式 p1 = Process(target=work_1) p2 = Process(target=work_2) p1.start() p2.start()
看過我之前寫的關於執行緒的那麼上面這段程式碼一定可以看懂,如果不明白可以回去看看關於執行緒的。
我們在多程式之間通訊需要用到佇列,但是這個佇列不是Queue.queue() 而是multiprrocessing中的Queue
queue.Queue 是程式內非阻塞佇列
multiprocessing.Queue 是跨程式通訊佇列
import requests
from multiprocessing import Process, Queue
def work_1(q): while q.qsize() > 0: url = q.get() requests.get(url) print('任務1') def work_2(q): while q.qsize() > 0: url = q.get() requests.get(url) print('任務2') if __name__ == '__main__': q = Queue() for i in range(10): q.put('http://localhost:3000/login') # 將q 這個例項化物件當作引數傳入函式中(不同的程式中),可以實現多程式共享變數,把這個佇列放到一個公共區間內 p1 = Process(target=work_1, args=(q,)) p2 = Process(target=work_2, args=(q,)) p1.start() p2.start()
下面來聊一聊程式池:
Pool可以提供指定數量的程式供使用者呼叫,當有新的請求提交到pool中時,如果池還沒有滿,那麼就會建立一個新的程式用來執行該請求;但如果池中的程式數已經達到規定最大值,那麼該請求就會等待,直到池中有程式結束,才會建立新的程式來它。
import requests
from multiprocessing import Pool, Manager # 程式池Pool Manager().Queue() # 程式池中的佇列
import time
import os # 檢視程式的pid
# a = Manager().Queue() # 程式池中的佇列
def work(q):
# 判斷佇列是否有任務
while q.qsize() > 0:
# 獲取任務
url = q.get()
requests.get(url)
print('任務1{}'.format(os.getpid()))
if __name__ == '__main__':
# 程式池中的佇列
q = Manager().Queue()
for i in range(10):
# 增加任務
q.put('http://localhost:3000/login')
# 建立程式池 最大程式數為3
p = Pool(3)
for i in range(10):
# 開啟程式執行任務 在程式池中,初始化幾個程式,輪詢執行任務,當一個任務執行完畢後這個程式會去執行另一個任務,直到所有任務完成
if q.qsize() > 0:
# 每次迴圈將會用空閒出來的子程式去呼叫目標
p.apply_async(work, args=(q,)) # 非同步的效率,也就是池中的程式一次性都去執行任務. 程式中有3個程式,一下就處理3個任務,接下來哪個程式處理完任務了,就馬上去接收下一個任務
p.close() # 程式池使用完畢一定要關閉程式池:停止往程式池中新增新的任務
p.join() # 等待po中所有子程式執行完成,必須在close之後 等待執行緒池中的所有任務都執行完了之後再往下執行
# 非同步處理任務時 : 必須要加上close和join. 程式池的所有程式都是守護程式(主程式程式碼執行結束,守護程式就結束).