2012-04-28 16 views
7

Estoy tratando de hablar con un proceso hijo utilizando la subproceso python.Popen() llamada. En mi código real, estoy implementando un tipo de IPC, por lo que quiero escribir algunos datos, leer la respuesta, escribir algunos datos más, leer la respuesta, etc. Debido a esto, no puedo usar Popen.communicate(), que de otra manera funciona bien para el caso simple.Lectura/escritura en un subproceso Popen()

Este código muestra mi problema. Nunca recibe la primera respuesta, se cuelga en el primer "resultado de lectura". ¿Por qué? ¿Cómo puedo hacer que esto funcione como espero? salida

import subprocess 
p = subprocess.Popen(["sed", 's/a/x/g'], 
        stdout = subprocess.PIPE, 
        stdin = subprocess.PIPE) 

p.stdin.write("abc\n") 
print "Reading result:" 
print p.stdout.readline() 

p.stdin.write("cat\n") 
print "Reading result:" 
print p.stdout.readline() 

Respuesta

4

me gustaría tratar de utilizar Popen().communicate() si puedes, ya que hace un montón de cosas buenas para ti, pero si es necesario utilizar Popen() exactamente como usted la describe, se tendrá que establecer sed para vaciar su memoria intermedia después de los saltos de línea con la opción -l:

p = subprocess.Popen(['sed', '-l', 's/a/x/g'], 
        stdout=subprocess.PIPE, 
        stdin=subprocess.PIPE) 

y su código debería funcionar bien

+1

De hecho, ¡funciona! Mi sed por alguna razón usa -u para "sin búfer", no -l, pero funciona de todos modos. Esto resuelve mi código de ejemplo, pero lamentablemente no es mi código real, ya que el comando real no está sed, sino otro programa de Python. Sin embargo, buena respuesta, identificaste el problema. –

+1

Sí, problema resuelto. El problema fue el almacenamiento en búfer de salida del resultado. Hacer un simple stdout.flush() en mi subproceso resolvió el problema. ¡Gracias! –

3

sed 's se tampona y sólo da salida a sus datos hasta que suficiente se ha acumulado o el flujo de entrada está agotado y cerrado.

Prueba esto:

import subprocess 
p = subprocess.Popen(["sed", 's/a/x/g'], 
        stdout = subprocess.PIPE, 
        stdin = subprocess.PIPE) 

p.stdin.write("abc\n") 
p.stdin.write("cat\n") 
p.stdin.close() 

print "Reading result 1:" 
print p.stdout.readline() 

print "Reading result 2:" 
print p.stdout.readline() 

Tenga en cuenta que esto no puede hacerse de forma fiable que gran cantidad de datos como wriring a stdin bloques una vez que el buffer está lleno. La mejor forma de hacerlo es usando communicate().

+0

Pero sed no actúa de esa manera cuando se ejecuta el comando en el shell directamente. Si haces eso, la respuesta viene después de cada línea. Y el problema persiste incluso si llamo a p.stdin.flush() después de escribir. Además, en la vida real, también he escrito el programa llamado, no hay memoria intermedia y se comporta de la misma manera. No estoy convencido de que el almacenamiento en memoria intermedia sea el problema aquí. –

+2

Ah, tenías razón, el buffering era de hecho el problema. –

Cuestiones relacionadas