examples example español python subprocess stdout popen

example - ¿Cómo recupero la información ''en tiempo real'' de un subproceso? Pobre en Python(2.5)



subprocess python 3 example (10)

Me gustaría utilizar el módulo de subproceso de la siguiente manera:

  1. crea un nuevo proceso que potencialmente toma mucho tiempo para ejecutarse.
  2. capture stdout (o stderr , o potencialmente ambos, juntos o por separado)
  3. Procese los datos del subproceso tal como viene, tal vez disparando eventos en cada línea recibida (en wxPython decir) o simplemente imprimiéndolos por el momento.

Creé procesos con Popen, pero si uso comunicar () los datos me llegan a todos al mismo tiempo, una vez que el proceso ha finalizado.

Si creo un hilo separado que hace una línea de myprocess.stdout de bloqueo readline() de myprocess.stdout (usando stdout = subprocess.PIPE ) tampoco obtengo ninguna línea con este método, hasta que el proceso finaliza. (no importa lo que configuro como bufsize)

¿Hay alguna forma de lidiar con esto que no sea horrible y que funcione bien en múltiples plataformas?


Actualiza con código que parece no funcionar (en Windows de todos modos)

class ThreadWorker(threading.Thread): def __init__(self, callable, *args, **kwargs): super(ThreadWorker, self).__init__() self.callable = callable self.args = args self.kwargs = kwargs self.setDaemon(True) def run(self): try: self.callable(*self.args, **self.kwargs) except wx.PyDeadObjectError: pass except Exception, e: print e if __name__ == "__main__": import os from subprocess import Popen, PIPE def worker(pipe): while True: line = pipe.readline() if line == '''': break else: print line proc = Popen("python subprocess_test.py", shell=True, stdin=PIPE, stdout=PIPE, stderr=PIPE) stdout_worker = ThreadWorker(worker, proc.stdout) stderr_worker = ThreadWorker(worker, proc.stderr) stdout_worker.start() stderr_worker.start() while True: pass


Esta parece ser una limitación bien conocida de Python, vea PEP 3145 y tal vez otros.


Esto es lo que funcionó para mí:

cmd = ["./tester_script.bash"] p = subprocess.Popen( cmd, shell=False, stdout=subprocess.PIPE, stderr=subprocess.PIPE ) while p.poll() is None: out = p.stdout.readline() do_something_with( out, err )

En su caso, podría intentar pasar una referencia al subproceso a su Subproceso de trabajo, y realizar la votación dentro del subproceso. No sé cómo se comportará cuando dos subprocesos sondean (e interactúan) el mismo subproceso, pero puede funcionar.

También tenga en cuenta que el while p.poll() is None: está destinado como está. No lo reemplace con while not p.poll() como en python 0 (el código de retorno para la finalización exitosa) también se considera False .



Lee un personaje a la vez: http://blog.thelinuxkid.com/2013/06/get-python-subprocess-output-without.html

import contextlib import subprocess # Unix, Windows and old Macintosh end-of-line newlines = [''/n'', ''/r/n'', ''/r''] def unbuffered(proc, stream=''stdout''): stream = getattr(proc, stream) with contextlib.closing(stream): while True: out = [] last = stream.read(1) # Don''t loop forever if last == '''' and proc.poll() is not None: break while last not in newlines: # Don''t loop forever if last == '''' and proc.poll() is not None: break out.append(last) last = stream.read(1) out = ''''.join(out) yield out def example(): cmd = [''ls'', ''-l'', ''/''] proc = subprocess.Popen( cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, # Make all end-of-lines ''/n'' universal_newlines=True, ) for line in unbuffered(proc): print line example()


Me he encontrado con este problema también. El problema ocurre porque también estás tratando de leer stderr. Si no hay errores, entonces tratar de leer desde stderr bloquearía.

En Windows, no hay una forma fácil de sondear los descriptores de archivos (solo los sockets de Winsock).

Entonces, una solución es no intentar leer de stderr.


Parece que el problema podría ser el uso de la salida almacenada en el subproceso; si se crea una cantidad relativamente pequeña de salida, podría almacenarse en el búfer hasta que salga el subproceso. Algunos antecedentes se pueden encontrar here :


Usar pexpect [ http://www.noah.org/wiki/Pexpect] con readlines sin bloqueo resolverá este problema. Se deriva del hecho de que las tuberías están almacenadas en un buffer, por lo que la salida de la aplicación está siendo amortiguada por la tubería, por lo tanto, no se puede acceder a esa salida hasta que se llene la memoria intermedia o el proceso se muera.


Utilizando el subproceso.Popen, puedo ejecutar el .exe de uno de mis proyectos C # y redireccionar el resultado a mi archivo Python. Ahora puedo print() toda la información que se envía a la consola C # (usando Console.WriteLine() ) a la consola de Python.

Código de Python:

from subprocess import Popen, PIPE, STDOUT p = Popen(''ConsoleDataImporter.exe'', stdout = PIPE, stderr = STDOUT, shell = True) while True: line = p.stdout.readline() print(line) if not line: break

Esto obtiene la salida de la consola de mi proyecto .NET línea por línea a medida que se crea y sale del bucle while mientras se termina el proyecto. Me imagino que esto también funcionaría para dos archivos de Python.


stdout se almacenará en el búfer, por lo que no obtendrá nada hasta que se llene ese búfer, o el subproceso salga.

Puede intentar eliminar el stdout del subproceso, o usar stderr, o cambiar el stdout en el modo sin búfer.