views:

112

answers:

1

I have a little command line tool that reads from stdin. On the command line I would run either...

./foo < bar

or ...

cat bar | ./foo

With a gziped file I can run

zcat bar.gz | ./foo

in Python I can do ...

Popen(["./foo", ], stdin=open('bar'), stdout=PIPE, stderr=PIPE)

but I can't do

import gzip
Popen(["./foo", ], stdin=gzip.open('bar'), stdout=PIPE, stderr=PIPE)

I wind up having to run

p0 = Popen(["zcat", "bar"], stdout=PIPE, stderr=PIPE)
Popen(["./foo", ], stdin=p0.stdout, stdout=PIPE, stderr=PIPE)

Am I doing something wrong? Why can't I use gzip.open('bar') as an stdin arg to Popen?

+2  A: 

Because the 'stdin' and 'stdout' of the subprocess takes file descriptor (which is a number), which is an operating system resource. This is masked by the fact that if you pass an object, the subprocess module checks whether the object has a 'fileno' attribute and if it has, it will use it.

The 'gzip' object is not something an operating system provides. An open file is, a socket is, a pipe is. Gzip object is an object that provides read() and write() methods but no fileno attribute.

You can look at the communicate() method of subprocess though, you might want to use it.

ondra
Yes, I am actually using p = Popen([...]) and then reading p.communicate()[0].Also, my program isn't called foo and my input file isn't called bar ;-)So you're saying there isn't an easy fix?I find it weird that Popen(["./foo", ], stdin=gzip.open('bar'), stdout=PIPE, stderr=PIPE)works (although returning bad output) and doesn't raise an exception. Its doing something with it even though it may not have a fileno attribute.
eric.frederich
The 'PIPE' and 'STDOUT' attributes from the subprocess module are 'special constants'; in case of stderr=STDOUT, the constant says that the fileno that should be passed to the client process should be the same, that is passed as stdout. In case of PIPE, a new fileno is created using the operating system 'pipe()' command, one half of the pipe (which is actually 2 numbers) is passed to the client process and one is given to you. Whatever is written to one part, can be read from the other. You cannot fix it easy way, more programming would be needed.
ondra