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]"


Related articles: