[prog] Python problem

David Sumbler david at aeolia.co.uk
Mon Jun 13 05:32:31 UTC 2011


I've been teaching myself Python, using Mark Lutz's generally excellent
O'Reilly books "Learning Python" (4th edition) and "Programming
Python" (4th edition).

In the chapter "Parallel System Tools" of the second book, I have come
across a problem which I can't fathom.  I've checked the book's website
and can find no reference to an error.  Unfortunately there doesn't
appear to be an associated forum or anywhere easily to ask about the
problem, but I thought that someone here might be able to suggest what
is going on.  Presumably the problem I am getting must be somewhat
unusual, otherwise I should expect there to be some correction or update
shown on the website.

These are the two relevant scripts.  They are actually the versions with
comments downloaded from the book's website, rather than the versions I
typed in myself (which I always do, as it helps me to learn), so typing
errors on my part do not arise!

#pipes.py:

"""
spawn a child process/program, connect my stdin/stdout to child
process's
stdout/stdin--my reads and writes map to output and input streams of the
spawned program; much like tying together streams with subprocess
module;
"""
import os, sys

def spawn(prog, *args):                    # pass progname, cmdline args
    stdinFd  = sys.stdin.fileno()          # get descriptors for streams
    stdoutFd = sys.stdout.fileno()         # normally stdin=0, stdout=1
    parentStdin, childStdout  = os.pipe()  # make two IPC pipechannels
    childStdin,  parentStdout = os.pipe()  # pipe returns (inputfd,
outoutfd)
    pid = os.fork()                        # make a copy of this process
    if pid:
        os.close(childStdout)            # in parent process after fork:
        os.close(childStdin)             # close child ends in parent
        os.dup2(parentStdin,  stdinFd)   # my sys.stdin copy  = pipe1[0]
        os.dup2(parentStdout, stdoutFd)  # my sys.stdout copy = pipe2[1]
    else
        os.close(parentStdin)            # in child process after fork:
        os.close(parentStdout)           # close parent ends in child
        os.dup2(childStdin,  stdinFd)    # my sys.stdin copy  = pipe2[0]
        os.dup2(childStdout, stdoutFd)   # my sys.stdout copy = pipe1[1]
        args = (prog,) + args
        os.execvp(prog, args)          # new program in this process
        assert False, 'execvp failed!' # os.exec call never returns here

if __name__ == '__main__':
    mypid = os.getpid()
    spawn('python', 'pipes-testchild.py', 'spam')   # fork child program

    print('Hello 1 from parent', mypid)        # to child's stdin
    sys.stdout.flush()                         # subvert stdio buffering
    reply = input()                            # from child's stdout
    sys.stderr.write('Parent got: "%s"\n' % reply)   # stderr not tied
to pipe!

    print('Hello 2 from parent', mypid)
    sys.stdout.flush()
    reply = sys.stdin.readline()
    sys.stderr.write('Parent got: "%s"\n' % reply[:-1])


#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


I've tried running pipes.py on two different computers.  One is running
Ubuntu 10.10, the other Ubuntu 10.04; both have Python 3.1, which is the
version the book is written for.  (I also have a handheld computer
running Windows XP Pro and Python 3.2, but because of the os.fork() call
the program fails on that system.)

Every time I run the program it falls over at the line "recv = input()"
in pipes-testchild.py:.  The full output from the program is:

Child 3951 of 3950 got arg: "spam"
Traceback (most recent call last):
  File "pipes-testchild.py", line 8, in <module>
    recv = input()
  File "<string>", line 1
    Hello 1 from parent 3950
          ^
SyntaxError: invalid syntax
Traceback (most recent call last):
  File "pipes.py", line 36, in <module>
    reply = input()
EOFError: EOF when reading a line


Presumably the second error (from pipes.py) arises because the other
process has already given up.

It looks to me as if, for some strange reason, pipes=testchild.py is
trying to interpret the input line 'Hello 1 from parent' as Python code,
but I can't imagine why it does this.  I've tried all the obvious
things, such as changing the content of the line, the name of the
variable, and so on.  I get exactly the same result on both computers.

Can anyone shed any light on what might be going wrong here?  I've spent
hours messing about with it, to no avail!

David



More information about the Programming mailing list