Prev: The real problem with Python 3 - no business case forconversion
Next: My extension code generator for C++
From: Sudheer on 3 Jul 2010 10:33 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 -- Thanks Sudheer
From: Chris Rebert on 3 Jul 2010 10:39 On Sat, Jul 3, 2010 at 7:33 AM, Sudheer <inbox1.sudheer(a)gmail.com> wrote: > 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 Try using .communicate() instead of reading and writing to .stdin and .stdout. Adding a newline (i.e. "hello\n") may also help. Cheers, Chris -- http://blog.rebertia.com
From: Nobody on 3 Jul 2010 16:11
On Sat, 03 Jul 2010 10:33:49 -0400, Sudheer wrote: > 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. |