subprocess query

S

Sudheer

Hi,
What's wrong with the following code. The program waits indefenitely
at 'output = p2.stdout.read()'


from subprocess import *

p1=Popen(['tr', 'a-z', 'A-Z'],stdin=PIPE,stdout=PIPE)
p2=Popen(['tr','A-Z', 'a-z'],stdin=p1.stdout,stdout=PIPE)
p1.stdin.write("hello")
p1.stdin.close()

output = p2.stdout.read()

print output
 
N

Nobody

What's wrong with the following code. The program waits indefenitely
at 'output = p2.stdout.read()'


from subprocess import *

p1=Popen(['tr', 'a-z', 'A-Z'],stdin=PIPE,stdout=PIPE)
p2=Popen(['tr','A-Z', 'a-z'],stdin=p1.stdout,stdout=PIPE)
p1.stdin.write("hello")
p1.stdin.close()

output = p2.stdout.read()

print output

The problem is that p2 is inheriting Python's copy of the write end of the
pipe corresponding to p1.stdin, which means that it's impossible to
generate EOF on the pipe (i.e. p1.stdin.close() is a no-op):

PID TTY STAT TIME COMMAND
30437 pts/1 S+ 0:00 /usr/bin/python2.6 ./test.py
30438 pts/1 S+ 0:00 tr a-z A-Z
30439 pts/1 S+ 0:00 tr A-Z a-z

/proc/30437/fd:
total 0
lrwx------ 1 user users 64 Jul 3 20:51 0 -> /dev/pts/1
lrwx------ 1 user users 64 Jul 3 20:51 1 -> /dev/pts/1
lrwx------ 1 user users 64 Jul 3 20:51 2 -> /dev/pts/1
lr-x------ 1 user users 64 Jul 3 20:51 3 -> pipe:[31472684]

/proc/30438/fd:
total 0
lr-x------ 1 user users 64 Jul 3 20:51 0 -> pipe:[31472681] <= ***
l-wx------ 1 user users 64 Jul 3 20:51 1 -> pipe:[31472682]
lrwx------ 1 user users 64 Jul 3 20:51 2 -> /dev/pts/1

/proc/30439/fd:
total 0
lr-x------ 1 user users 64 Jul 3 20:51 0 -> pipe:[31472682]
l-wx------ 1 user users 64 Jul 3 20:51 1 -> pipe:[31472684]
lrwx------ 1 user users 64 Jul 3 20:51 2 -> /dev/pts/1
l-wx------ 1 user users 64 Jul 3 20:51 4 -> pipe:[31472681] <= ***

On Unix, you can add close_fds=True when creating p2, but that won't work
on Windows (it prevents redirection of stdin/stdout/stderr). OTOH, I don't
know whether the problem exists on Windows; if it doesn't just set
close_fds to True on Unix and False on Windows.

Alternatively, on Unix you should be able to use:

fcntl(fd, F_SETFD, FD_CLOEXEC)

(from the fcntl module) to prevent the write end of the pipe from being
inherited.

Worse still, killing the script with Ctrl-C will leave both of the child
processes behind.

In C, you would typically close the unused ends of the pipes within the
child half of the fork(), before the exec(), but you don't have that
degree of control with subprocess.

On Windows, you can chose whether a handle is inheritable or not, but I
don't know whether you can do that from within Python.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,770
Messages
2,569,583
Members
45,072
Latest member
trafficcone

Latest Threads

Top