标题 | python进程通信之匿名管道实例讲解 |
内容 | 匿名管道 管道是一个单向通道,有点类似共享内存缓存.管道有两端,包括输入端和输出端.对于一个进程的而言,它只能看到管道一端,即要么是输入端要么是输出端. os.pipe()返回2个文件描述符(r, w),表示可读的和可写的.示例代码如下: 代码如下: #!/usr/bin/python import time import os def child(wpipe): print('hello from child', os.getpid()) while true: msg = 'how are you\n'.encode() os.write(wpipe, msg) time.sleep(1) def parent(): rpipe, wpipe = os.pipe() pid = os.fork() if pid == 0: child(wpipe) assert false, 'fork child process error!' else: os.close(wpipe) print('hello from parent', os.getpid(), pid) fobj = os.fdopen(rpipe, 'r') while true: recv = os.read(rpipe, 32) print recv parent() 输出如下: 代码如下: ('hello from parent', 5053, 5054) ('hello from child', 5054) how are you how are you how are you how are you 我们也可以改进代码,不用os.read()从管道中读取二进制字节,而是从文件对象中读取字符串.这时需要用到os.fdopen()把底层的文件描述符(管道)包装成文件对象,然后再用文件对象中的readline()方法读取.这里请注意文件对象的readline()方法总是读取有换行符'\n'的一行,而且连换行符也读取出来.还有一点要改进的地方是,把父进程和子进程的管道中不用的一端关闭掉. 代码如下: #!/usr/bin/python import time import os def child(wpipe): print('hello from child', os.getpid()) while true: msg = 'how are you\n'.encode() os.write(wpipe, msg) time.sleep(1) def parent(): rpipe, wpipe = os.pipe() pid = os.fork() if pid == 0: os.close(rpipe) child(wpipe) assert false, 'fork child process error!' else: os.close(wpipe) print('hello from parent', os.getpid(), pid) fobj = os.fdopen(rpipe, 'r') while true: recv = fobj.readline()[:-1] print recv parent() 输出如下: 代码如下: ('hello from parent', 5108, 5109) ('hello from child', 5109) how are you how are you how are you 如果要与子进程进行双向通信,只有一个pipe管道是不够的,需要2个pipe管道才行.以下示例在父进程新建了2个管道,然后再fork子进程.os.dup2()实现输出和输入的重定向.spawn功能类似于subprocess.popen(),既能发送消息给子进程,由能从子子进程获取返回数据. 代码如下: #!/usr/bin/python #coding=utf-8 import os, sys def spawn(prog, *args): stdinfd = sys.stdin.fileno() stdoutfd = sys.stdout.fileno() parentstdin, childstdout = os.pipe() childstdin, parentstdout= os.pipe() pid = os.fork() if pid: os.close(childstdin) os.close(childstdout) os.dup2(parentstdin, stdinfd)#输入流绑定到管道,将输入重定向到管道一端parentstdin os.dup2(parentstdout, stdoutfd)#输出流绑定到管道,发送到子进程childstdin else: os.close(parentstdin) os.close(parentstdout) os.dup2(childstdin, stdinfd)#输入流绑定到管道 os.dup2(childstdout, stdoutfd) args = (prog, ) + args os.execvp(prog, args) assert false, 'execvp failed!' if __name__ == '__main__': mypid = os.getpid() spawn('python', 'pipetest.py', 'spam') print 'hello 1 from parent', mypid #打印到输出流parentstdout, 经管道发送到子进程childstdin sys.stdout.flush() reply = raw_input() sys.stderr.write('parent got: %s\n' % reply)#stderr没有绑定到管道上 print 'hello 2 from parent', mypid sys.stdout.flush() reply = sys.stdin.readline()#另外一种方式获得子进程返回信息 sys.stderr.write('parent got: %s\n' % reply[:-1]) pipetest.py代码如下: 代码如下: #coding=utf-8 import os, time, sys mypid = os.getpid() parentpid = os.getppid() sys.stderr.write('child %d of %d got arg: %s\n' %(mypid, parentpid, sys.argv[1])) for i in range(2): time.sleep(3) recv = raw_input()#从管道获取数据,来源于父经常stdout time.sleep(3) send = 'child %d got: [%s]' % (mypid, recv) print(send)#stdout绑定到管道上,发送到父进程stdin sys.stdout.flush() 输出: 代码如下: child 7265 of 7264 got arg: spam parent got: child 7265 got: [hello 1 from parent 7264] parent got: child 7265 got: [hello 2 from parent 7264] |
随便看 |
|
在线学习网考试资料包含高考、自考、专升本考试、人事考试、公务员考试、大学生村官考试、特岗教师招聘考试、事业单位招聘考试、企业人才招聘、银行招聘、教师招聘、农村信用社招聘、各类资格证书考试等各类考试资料。