2010-04-28 17 views
6

Tengo una pequeña herramienta de línea de comandos que lee de stdin. En la línea de comandos me iría bien ...¿Puedo usar un archivo gzip abierto con Popen en Python?

./foo < bar 

o ...

cat bar | ./foo 

Con un archivo gziped puedo correr

zcat bar.gz | ./foo 

en Python que puedo hacer. ..

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

pero yo no puede hacer

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

termino tener que ejecutar

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

¿Estoy haciendo algo mal? ¿Por qué no puedo usar gzip.open ('bar') como stdin arg a Popen?

Respuesta

4

Porque 'stdin' y 'stdout' del subproceso toman el descriptor de archivo (que es un número), que es un recurso del sistema operativo. Esto está enmascarado por el hecho de que si pasa un objeto, el módulo de subproceso verifica si el objeto tiene un atributo 'fileno' y si lo tiene, lo usará.

El objeto 'gzip' no es algo que proporciona un sistema operativo. Un archivo abierto es, un socket es, un tubo es. El objeto Gzip es un objeto que proporciona los métodos read() y write() pero no el atributo fileno.

Sin embargo, puede mirar el método de subproceso comunicar(), es posible que desee utilizarlo.

+0

Sí, en realidad estoy usando p = Popen ([...]) y luego estoy leyendo p.communicate() [0]. Además, mi programa no se llama foo y mi archivo de entrada no se llama bar ;-) ¿Estás diciendo que no hay una solución fácil? Me resulta extraño que Popen (["./ foo",], stdin = gzip.open ('bar'), stdout = PIPE, stderr = PIPE) funciona (aunque devuelve un resultado incorrecto) y no genera una excepción. Está haciendo algo con él aunque no tenga un atributo fileno. –

+0

Los atributos 'PIPE' y 'STDOUT' del módulo de subproceso son 'constantes especiales'; en el caso de stderr = STDOUT, la constante dice que el archivo que se debe pasar al proceso del cliente debe ser el mismo, que se pasa como stdout. En el caso de PIPE, se crea un nuevo archivo utilizando el comando del sistema operativo 'pipe()', la mitad del conducto (que en realidad son 2 números) se pasa al proceso del cliente y se le da uno. Lo que está escrito en una parte, se puede leer en la otra. No se puede arreglar de manera fácil, se necesitaría más programación. – ondra

Cuestiones relacionadas