Estoy usando pty
para leer sin bloquear la salida estándar de un proceso como este:
import os import pty import subprocess master, slave = pty.openpty() p = subprocess.Popen(cmd, stdout = slave) stdout = os.fdopen(master) while True: if p.poll() != None: break print stdout.readline() stdout.close()
Todo funciona bien, excepto que el while-loop
vez en cuando se bloquea. Esto se debe al hecho de que la línea de print stdout.readline()
está esperando que se lea algo de la print stdout.readline()
. Pero si el progtwig ya terminó, mi pequeño script allí colgará para siempre.
Mi pregunta es: ¿hay una manera de mirar dentro del objeto stdout
y verificar si hay datos disponibles para leer? Si este no es el caso, debe continuar a través del while-loop
donde descubrirá que el proceso ya terminó y rompe el bucle.
Sí, use la encuesta del módulo de selección :
import select q = select.poll() q.register(stdout,select.POLLIN)
y al mismo tiempo usar:
l = q.poll(0) if not l: pass # no input else: pass # there is some input
La respuesta de select.poll () es muy clara, pero no funciona en Windows. La siguiente solución es una alternativa. No le permite ver la salida estándar, pero proporciona una alternativa de no locking a readline () y se basa en esta respuesta :
from subprocess import Popen, PIPE from threading import Thread def process_output(myprocess): #output-consuming thread nextline = None buf = '' while True: #--- extract line using read(1) out = myprocess.stdout.read(1) if out == '' and myprocess.poll() != None: break if out != '': buf += out if out == '\n': nextline = buf buf = '' if not nextline: continue line = nextline nextline = None #--- do whatever you want with line here print 'Line is:', line myprocess.stdout.close() myprocess = Popen('myprogram.exe', stdout=PIPE) #output-producing process p1 = Thread(target=process_output, args=(dcmpid,)) #output-consuming thread p1.daemon = True p1.start() #--- do whatever here and then kill process and thread if needed if myprocess.poll() == None: #kill process; will automatically stop thread myprocess.kill() myprocess.wait() if p1 and p1.is_alive(): #wait for thread to finish p1.join()
Otras soluciones para la lectura sin locking se han propuesto aquí , pero no funcionaron para mí: