Tengo algunas dificultades para obtener resultados de una tubería de subproceso stdout. Estoy lanzando un código de terceros a través de él, para extraer la salida de registro. Hasta una actualización reciente del código de un tercero, todo funcionó bien. Después de la actualización, Python ha comenzado a bloquear de forma indefinida y no muestra ningún resultado. Puedo iniciar manualmente la aplicación de terceros y ver resultados.Salida del subproceso Python en Windows?
Una versión básica del código que estoy usando:
import subprocess, time
from threading import Thread
def enqueue_output(out):
print "Hello from enqueue_output"
for line in iter(out.readline,''):
line = line.rstrip("\r\n")
print "Got %s" % line
out.close()
proc = subprocess.Popen("third_party.exe", stdout=subprocess.PIPE, bufsize=1)
thread = Thread(target=enqueue_output, args=(proc.stdout,))
thread.daemon = True
thread.start()
time.sleep(30)
Esto funciona perfectamente si sustituyo third_party.exe para este script:
import time, sys
while True:
print "Test"
sys.stdout.flush()
time.sleep(1)
Así que estoy claro en cuanto a la magia debe hacerse para que esto funcione con el comando original.
Estas son todas las variantes de la línea subprocess.Popen que he probado sin éxito:
proc = subprocess.Popen("third_party.exe", stdout=subprocess.PIPE, bufsize=0)
proc = subprocess.Popen("third_party.exe", stdout=subprocess.PIPE, shell=True)
proc = subprocess.Popen("third_party.exe", stdout=subprocess.PIPE, creationflags=subprocess.CREATE_NEW_CONSOLE)
si = subprocess.STARTUPINFO()
si.dwFlags = subprocess.STARTF_USESTDHANDLES | subprocess.STARTF_USESHOWWINDOW
proc = subprocess.Popen("third_party.exe", stdout=subprocess.PIPE, startupinfo=si)
Edición 1: no puedo utilizar realmente .communicate() en este caso. La aplicación que estoy lanzando sigue ejecutándose durante largos períodos de tiempo (días o semanas). La única forma en que podría probar .communicate() sería matar la aplicación poco después de su lanzamiento, lo que no creo que me daría resultados válidos.
Incluso la versión no roscada de esta falla:
import subprocess, time
from threading import Thread
proc = subprocess.Popen("third_party.exe", stdout=subprocess.PIPE, stderr=subprocess.PIPE)
print "App started, reading output..."
for line in iter(proc.stdout.readline,''):
line = line.rstrip("\r\n")
print "Got: %s" % line
Edición 2: Gracias a jdi, las siguientes obras okay:
import tempfile, time, subprocess
w = "test.txt"
f = open("test.txt","a")
p = subprocess.Popen("third_party.exe", shell=True, stdout=f,
stderr=subprocess.STDOUT, bufsize=0)
time.sleep(30)
with open("test.txt", 'r') as r:
for line in r:
print line
f.close()
¿Es posible que su programa de terceros haya cambiado a la escritura en stderr? – jdi
No parece ser el caso. Si intercepto stderr, sucede lo mismo (aunque veo la salida de la aplicación en la consola, pero solo imprime, no está pasando por Python). – devicenull
Parece que la aplicación ha dejado de usar la salida estándar y está escribiendo directamente en la consola. Si es así, no hay mucho que puedas hacer al respecto. ¿Puedes consultar con el proveedor de la aplicación? –