An example of an anonymous pipe for Python process communication
- 2020-05-09 18:47:19
- OfStack
Anonymous pipe
A pipe is a one-way channel, similar to a Shared memory cache. The pipe has two sides, including the input and output ends. For a process, it can only see the one end of the pipe, which is either the input or the output end.
os.pipe () returns two file descriptors (r, w), representing both readable and writable.
#!/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()
The output is as follows:
('hello from parent', 5053, 5054)
('hello from child', 5054)
how are you
how are you
how are you
how are you
. We can also improve code, without os read () two hexadecimal bytes read from the pipeline, but reads a string from the file object. At this moment need os. fdopen () at the bottom of the file descriptor (pipe) as object, and then use the file object readline read () method. Please note that the file object readline here () method always read a newline character '\ n 1 row, and even read out a newline. There is 1 point to improve, the parent and child process pipeline in no 1 Shut off.
#!/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()
The output is as follows:
('hello from parent', 5108, 5109)
('hello from child', 5109)
how are you
how are you
how are you
If you want a two-way communication with the child, only one pipe pipe is not enough, need two pipe pipeline. The following example in the parent process has built two pipes, and then fork child. os. dup2 () implementation of output and input redirection. spawn function similar to subprocess. Popen (), can send a message to the child, can obtain data returned from the child the child.
#!/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)# The input stream is bound to the pipe , Redirect the input to the pipe 1 end parentStdin
os.dup2(parentStdout, stdoutFd)# The output stream is bound to the pipe , Send to child process childStdin
else:
os.close(parentStdin)
os.close(parentStdout)
os.dup2(childStdin, stdinFd)# The input stream is bound to the pipe
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 # Print to the output stream parentStdout, It is piped to the child process childStdin
sys.stdout.flush()
reply = raw_input()
sys.stderr.write('Parent got: "%s"\n' % reply)#stderr Not bound to the pipe
print 'Hello 2 from parent', mypid
sys.stdout.flush()
reply = sys.stdin.readline()# In addition 1 Way to get the child process return information
sys.stderr.write('Parent got: "%s"\n' % reply[:-1])
pipetest.py code is as follows:
#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()# Get data from the pipeline , From the father often stdout
time.sleep(3)
send = 'Child %d got: [%s]' % (mypid, recv)
print(send)#stdout Bind to the pipe , Send to the parent process stdin
sys.stdout.flush()
Output:
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]"