python进程通信之匿名管道实例讲解
来源: 阅读:1249 次 日期:2016-06-22 10:32:12
温馨提示: 小编为您整理了“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]

更多信息请查看 脚本栏目
由于各方面情况的不断调整与变化, 提供的所有考试信息和咨询回复仅供参考,敬请考生以权威部门公布的正式信息和咨询为准!
关于我们| 联系我们| 人才招聘| 网站声明| 网站帮助| 非正式的简要咨询| 简要咨询须知| 加入群交流| 手机站点| 投诉建议
工业和信息化部备案号:滇ICP备2023014141号-1 云南省教育厅备案号:云教ICP备0901021 滇公网安备53010202001879号 人力资源服务许可证:(云)人服证字(2023)第0102001523号
云南网警备案专用图标
联系电话:0871-65317125(9:00—18:00) 获取招聘考试信息及咨询关注公众号:
咨询QQ:526150442(9:00—18:00) 版权所有:
云南网警报警专用图标
Baidu
map