能批量产生进程。
采用Process类创建进程。用于创建代码可控的进程,非脚本执行进程和系统命令进程。
创建两个队列,分别作为两个进程的读写管道。
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。
两个完全独立的进程,一般采用命名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'}