what happens to Popen()'s parent-side file descriptors?

Roger Davis rbd at hawaii.edu
Wed Oct 13 23:58:57 CEST 2010


Hi, I am new to this group, please forgive me if this is a repeat
question. I am a new Python programmer but experienced in C/Unix. I am
converting a shell script to Python which essentially loops
infinitely, each pass through the loop running commands like

      set output = `cat this | grep that | whatever ...`

My understanding is that this functionality is best coded via
subprocess.Popen(). I need to read output from these spawned children
via a pipe from their stdout, hence something like

     p= subprocess.Popen(args, stdout=subprocess.PIPE)

This means that somewhere a pipe file descriptor is opened on the
parent side to read from the child's stdout. When, if ever, is that
descriptor closed? Per-process FDs are limited and I am looping
infinitely so I need to be very careful about not running out of them.
Are there any other FDs related to this operation that also need to be
closed?

Testing with the interpreter (2.6, MacOSX) it appears that p.stdout is
being closed somehow by someone other than me:

import subprocess
args= ["echo", "This is a mystery!"]
i= 0
while True:
    p= subprocess.Popen(args, stdout=subprocess.PIPE)
    for line in p.stdout:
        print "[%5d] %s" % (i, line.strip())
    i+= 1

The above code closes nothing but appears to run indefinitely without
running the parent out of FDs. WTF is going on here?

Popen.communicate() similarly appears to be closing the parent's pipe
FDs, although that seems more understandable as it appears to be
designed to encapsulate a lot of cleanup activity. In either case
(code snippet above or communicate() an attempt to manually close
p,stdout goes as follows:

>>> print p.stdout.close()
None

Attempts to close anything else fail spectacularly as one might
expect:

>>> print p.stdin.close()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'NoneType' object has no attribute 'close'

Can anyone explain the treatment of the pipe FDs opened in the parent
by Popen() to me or point me to some documentation? The python.org
docs say absolutely nothing about this as far as I can tell, a glaring
deficiency IMO (hint to all you underworked volunteer developers ;-
> ).

Also, does Popen.returncode contain only the child's exit code or is
does it also contain signal info like the return of os.wait()?
Documentation on this is also unclear to me.

Thanks very much!



More information about the Python-list mailing list