1. 程式人生 > >python中multiprocessing模組之Pipe管道

python中multiprocessing模組之Pipe管道

原文地址,本文在原文基礎上添加了部分註釋。

multiprocessing.Pipe([duplex]) 方法返回2個連線物件(conn1, conn2),代表管道的兩端,預設duplex為True,是雙向通訊。如果duplex為False,則conn1只能用來接收訊息,conn2只能用來發送訊息。

例項如下:

#!/usr/bin/python
#coding=utf-8
import os
from multiprocessing import Process, Pipe

def send(pipe):
    pipe.send(['spam'] + [42, 'egg'])
    pipe.close()

def
talk(pipe):
pipe.send(dict(name = 'Bob', spam = 42)) reply = pipe.recv() print('talker got:', reply) if __name__ == '__main__': (con1, con2) = Pipe() #Pipe()構造器直接返回一對連線物件,這兩個物件之間可以首發內容 sender = Process(target = send, name = 'send', args = (con1, )) sender.start() print(
"con2 got: %s" % con2.recv())#從send收到訊息 con2.close() (parentEnd, childEnd) = Pipe() child = Process(target = talk, name = 'talk', args = (childEnd,)) child.start() print('parent got:', parentEnd.recv()) parentEnd.send({x * 2 for x in 'spam'}) child.join() print('parent exit'
)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28

輸出如下:

con2 got: ['spam', 42, 'egg']
('parent got:', {'name': 'Bob', 'spam': 42})
('talker got:', set(['ss', 'aa', 'pp', 'mm']))
parent exit

程式碼中send方法是利用管道傳送一個列表,列表內容為['spam',42,'egg'],而程式碼talk是利用管道傳送一個字典,再接收一個內容,接收的內容來自與之配對的另一個管道。示例程式碼中會分別測試send方法和talk方法。

示例程式碼16至20行是用來測試send方法的。使用管道是進行跨程序通訊,因此第17行程式碼中啟動一個程序,在該程序中執行send方法,在send方法中用管道con1來發送列表,在主程序中用與con1配對的con2來接收內容,並將接收到的內容列印到控制檯。從而完成了send程序去主程序之間內容的傳遞。

22至28行用來測試talk方法,兩個管道都進行了訊息的收和發。第23行建立了單獨的talk程序並啟動,在talk程序中執行talk方法,即利用childEnd管道傳送一個字典,隨後childEnd管道進入一個接收狀態,一直等待與childEnd配對的parentEnd管道傳送的內容。第25行,在主程序中,parentEnd管道接收到childEnd管道傳送的內容,然後parentEnd將收到的內容做一個簡單的處理後進行傳送,此時傳送的內容會被talk程序的childEnd管道的recv接收到並在talk程序是talk方法中進行列印。隨後talk方法執行完畢,talk程序執行完畢。

如果將第26行程式碼註釋掉,則主程序和talk程序都會被卡住。這是因為,第27行的child.join()方法決定了主程序必須等待talk程序執行完畢(並將其關閉)後才可以執行執行。但是此時talk程序會卡在第12行一直等到parentEnd傳送內容過來,不然會一直等待。如果一直等待的話,talk執行緒並不會結束,talk不結束主程序也會卡在第27行不能往下執行。