Python subproceso Popen readline antes de cerrar stdin

Sep 07 2020
import subprocess as sp

p = sp.Popen("/bin/cat", stdin=sp.PIPE, stdout=sp.PIPE)

p.stdin.write(b"foobaz!\n")
p.stdin.close()
print(p.stdout.readline())

Este código funciona como se esperaba (cat se hace eco del stdin y podemos leer el stdout)

Si comentamos el p.stdin.close(), los .readline()bloques indefinidamente. En su lugar, se comporta de la misma manera .read(1). ¿Hay alguna forma de readline usando el módulo de subproceso sin enviar EOF a stdin?

Soy consciente de que hay otras bibliotecas que podrían resolver mi problema y también las estoy investigando. Para esta pregunta, solo tengo curiosidad por saber si subprocesstiene esta capacidad y cómo lograrla subprocess.

Respuestas

1 alani Sep 07 2020 at 12:28

El problema está en el almacenamiento en búfer. Puede usar bufsize=1si también usa universal_newlines=True(aunque luego escribiría cadenas en lugar de bytes):

p = sp.Popen("/bin/cat", stdin=sp.PIPE, stdout=sp.PIPE, 
             bufsize=1, universal_newlines=True)
p.stdin.write("foobaz!\n")
print(p.stdout.readline())

Lo anterior se prueba en Python 3.5.2. Nota: por separado, acabo de leer una respuesta a una pregunta no relacionada que sugiere que en versiones más recientes de Python text=Truees equivalente a universal_newlines=True, pero no tengo una instalación más reciente para probarlo al momento de escribir.