[Python编程(第4版)].(Programming.Python.4th.Edition).Mark.Lutz.文字版

(yzsuai) #1

To test this utility, the self-test code at the end of the file spawns the program shown
in Example 5-23 in a child process and reads and writes standard streams to converse
with it over two pipes.


Example 5-23. PP4E\System\Processes\pipes-testchild.py


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) # make parent process wait by sleeping here
recv = input() # stdin tied to pipe: comes from parent's stdout
time.sleep(3)
send = 'Child %d got: [%s]' % (mypid, recv)
print(send) # stdout tied to pipe: goes to parent's stdin
sys.stdout.flush() # make sure it's sent now or else process blocks


The following is our test in action on Cygwin (it’s similar other Unix-like platforms like
Linux); its output is not incredibly impressive to read, but it represents two programs
running independently and shipping data back and forth through a pipe device man-
aged by the operating system. This is even more like a client/server model (if you imag-
ine the child as the server, responding to requests sent from the parent). The text in
square brackets in this output went from the parent process to the child and back to
the parent again, all through pipes connected to standard streams:


[C:\...\PP4E\System\Processes]$ python pipes.py
Child 9228 of 9096 got arg: "spam"
Parent got: "Child 9228 got: [Hello 1 from parent 9096]"
Parent got: "Child 9228 got: [Hello 2 from parent 9096]"

Output stream buffering revisited: Deadlocks and flushes


The two processes of the prior section’s example engage in a simple dialog, but it’s
already enough to illustrate some of the dangers lurking in cross-program communi-
cations. First of all, notice that both programs need to write to stderr to display a
message; their stdout streams are tied to the other program’s input stream. Because
processes share file descriptors, stderr is the same in both parent and child, so status
messages show up in the same place.


More subtly, note that both parent and child call sys.stdout.flush after they print text
to the output stream. Input requests on pipes normally block the caller if no data is
available, but it seems that this shouldn’t be a problem in our example because there
are as many writes as there are reads on the other side of the pipe. By default, though,
sys.stdout is buffered in this context, so the printed text may not actually be transmitted
until some time in the future (when the output buffers fill up). In fact, if the flush calls
are not made, both processes may get stuck on some platforms waiting for input from
the other—input that is sitting in a buffer and is never flushed out over the pipe. They


Interprocess Communication | 231
Free download pdf