MultiProcessing中主进程与子进程之间通过管道(Pipe)通信
Python 中 Multiprocessing 實現進程通信
- 1. 如何建立主進程與子進程之間的通信管道?
- 2. 為什么一定要將Pipe中的某些端close()?
本文參考自:python 學習筆記 - Queue & Pipes,進程間通訊
1. 如何建立主進程與子進程之間的通信管道?
在Python中很多時候需要用到多進程并行編程,由于每個進程都擁有自己的獨立內存空間,無法像線程一樣通過訪問全局變量來共享數據。因此,進程之間的通信比線程通信要更加的復雜。在 Multiprocessing 包中存在 Pipe 類,Pipe(管道)能夠實現進程之間更高效的通信,倘若我們現在由一個主進程,主進程創建了一個子進程,那么如何通過建立主進程與子進程之間的通信呢?
- 當主進程創建Pipe的時候,Pipe的兩個Connections連接的都是主進程;
- 當主進程創建子進程后,Connections被拷貝了一份,此時一共有2(主進程)+ 2(子進程)= 4 個Connections;
- 隨后,我們關閉主進程中的 out_connection 和子進程中的 in_connection 端口,即可建立一條主進程通往子進程的管道了;
NOTE: in_connection 和 out_connection 中的 in/out 是針對 Pipe 管道來說的,in 是指數據流入Pipe的那條管道。此外,由于 Pipe 對象默認是雙向的,因此下圖中的箭頭管道上的數據流實際上可以是雙向的,既能從上往下也能從下往上。
實現代碼如下所示:
from multiprocessing import Pipe, Processdef son_process(x, pipe):""" 注意,out在前,in在后 """_out_pipe, _in_pipe = pipe""" 關閉拷貝過來的輸入端 """_in_pipe.close()while True:try:msg = _out_pipe.recv()print msgexcept EOFError:""" 當out_pipe接受不到輸出的時候且輸入被關閉的時候,會拋出EORFError,可以捕獲并且退出子進程 """breakif __name__ == '__main__':out_pipe, in_pipe = Pipe(True)son_p = Process(target=son_process, args=(100, (out_pipe, in_pipe)))son_p.start()""" 等pipe被拷貝后,關閉主進程的輸出端,這樣,創建的Pipe一端連接著主進程的輸入,一端連接著子進程的輸出口 """out_pipe.close()for x in range(1000):in_pipe.send(x)in_pipe.close()son_p.join()print("主進程結束")2. 為什么一定要將Pipe中的某些端close()?
由于Pipe之間的通信時通過,in_conn.send()、out_conn.recv() 這種方式進行通信的,因此如果當某一方調用了 .recv() 函數但一直沒有另外的端口使用 .send() 方法的話,recv() 函數就會阻塞住。為了避免程序阻塞,我們在明確另一個端口不會再調用 .send() 函數后可以直接將發送端口給 close(),這樣以來如果接收端還在繼續調用 .recv() 方法的話程序就會拋出 EOFError 的異常,示例代碼如下:
from multiprocessing import Process from multiprocessing import Pipe import os import timedef send(out_conn):out_conn.send("hello")""" 發完一次內容后,就將子進程中的 out_conn 給 close(),注意外部(主進程中)的 out_conn 也需要被 close """out_conn.close() def recv(in_conn):try:print(in_conn.recv())print(in_conn.recv()) # 第二次調用 .recv() 會拋出 EOFError 異常,因為 out_conn 已經被關閉了except EOFError:print("end")if __name__ == "__main__":out_conn, in_conn = Pipe(True)p_send = Process(target=send, args=(out_conn,))p_send.start()p_recv = Process(target=recv, args=(in_conn,))p_recv.start()out_conn.close() # 在子進程拷貝完 Pipe Connections 之后,外部的 out_conn 也需要被關閉p_send.join()p_recv.join()總結
以上是生活随笔為你收集整理的MultiProcessing中主进程与子进程之间通过管道(Pipe)通信的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 多智能体连续行为空间问题求解——MADD
- 下一篇: 【QMIX】一种基于Value-Base