利用multiprocessing做进程间通信

 

3.3 multiprocess 创建进程

         能批量产生进程。

         采用Process类创建进程。用于创建代码可控的进程,非脚本执行进程和系统命令进程。

3.3.1 建立两个子进程的Queue通信

         创建两个队列,分别作为两个进程的读写管道。

q1 = Queue()
q2 = Queue()

consoleP = Process(target=script_runner.startConsole args=(q2, q1,))
httpP = Process(target=httpserver.startServer, args=(q1, q2,))

consoleP.start()
time.sleep(3)
httpP.start()

script_runner.startConsole :进程入口函数

httpserver.startServer:进程入口函数

 

         如上面代码,可以定义q1队列为:进程consoleP写数据,进程httpP读数据;q2队列为:进程consoleP读数据,进程httpP写数据。

         一个进程崩溃,可以根据持有的队列进行恢复。此处存在3个进程,任何一个进程崩溃,均不会影响其他进程。可以设定异常,验证。

         例如异常代码:str ="" + 1

         缺陷:如果一方启动的进程是httpserver,例如SimpleHttpServer,有自己的进程恢复机制,则无法恢复队列通信。

         此时考虑用用pythonConnect类对象处理子进程之间的通信,也适合完全无关的两个进程间的通信,如章节3.3.2。

 

3.3.2 完全独立进程间的通信

         两个完全独立的进程,一般采用命名Pipe或者Socket通信,在windows下,python没有实现命名pipe。另外,python实现了更高层级的通信机制,Listener和Client机制。

         Listener服务端:

address = ("localhost", 8000)
listener = Listener(address, authkey="password")
print "Accept"
conn = listener.accept()
print conn.recv()

 

         Client客户端:

address = ("localhost", 8000) 
conn = Client(address,authkey="password")
time.sleep(5)
dict = {"action":"testbase"}
conn.send(json.dumps(dict))

        

         如果两个进程均要主动发送请求,则考虑建立两个通信链路。如下面实现类:

class HttpConsoleBinder():
    HttpServer_Port = 6000
    Console_Port = HttpServer_Port + 1
    def __init__(self):
        self.httpAddress = ("localhost", HttpConsoleBinder.HttpServer_Port)
        self.consoleAddress = ("localhost", HttpConsoleBinder.Console_Port)

    def initHttpListener(self):
        self.httpListener = Listener(self.httpAddress, authkey="password")

    def initConsoleListener(self):
        self.consoleListener = Listener(self.consoleAddress, authkey="password")

    def sendToHttp(self,action, data):
        self.httpClient = Client(self.httpAddress, authkey="password")
        data["action"] = action
        jsonStr = json.dumps(data)
        try:
            self.httpClient.send(jsonStr)
        except Exception,e:
            print e
        finally:
            self.httpClient.close()

    def sendToConsole(self, action, data):
        self.consoleClient = Client(self.consoleAddress, authkey="password")
        data["action"] = action
        jsonStr = json.dumps(data)
        try:
            self.consoleClient.send(jsonStr)
        except Exception,e:
            print e
        finally:
            self.consoleClient.close()

    def acceptHttp(self):
        conn = self.consoleListener.accept()
        data = conn.recv()
        dataDict = json.loads(data)
        action = dataDict["action"]
        conn.close()
        return action,dataDict

    def acceptConsole(self):
        conn = self.httpListener.accept()
        data = conn.recv()
        dataDict = json.loads(data)
        action = dataDict["action"]
        conn.close()
        return action,dataDict

 

         上面的类针对两个终端:Http和Console

         双向测试代码如下:

def testP1():
    binder = HttpConsoleBinder()
    binder.initConsoleListener()
    print "Wait http"
    action,data = binder.acceptHttp()
    print "testP1,action:",action,";data:",data
    print "Send to http"
    binder.sendToHttp("test", {"keyP1": "valueP1"})

def testP2():
    binder = HttpConsoleBinder()
    binder.initHttpListener()
    print "Send to console"
    binder.sendToConsole("test", {"keyP2":"valueP2"})
    print "Wait console"
    action,data = binder.acceptConsole()
    print "testP2,action:",action,";data:",data
 
if __name__ == "__main__":

    q1 = Queue()
    q2 = Queue()
    p1 = Process(target=testP1, args=())
    p1.start()
    time.sleep(3)
    p2 = Process(target=testP2, args=())
    p2.start()

可以看到打印如下:

Wait http

Send to console

Wait console

testP1,action: test ;data: {u'action':u'test', u'keyP2': u'valueP2'}

Send to http

testP2,action: test ;data: {u'action':u'test', u'keyP1': u'valueP1'}

你可能感兴趣的:(开发,python,多进程)