examples example espaƱol python subprocess pipe stdout deadlock

python - example - Necesidad de evitar el bloqueo de subproceso sin comunicarse.



subprocess python 3 example (5)

Necesito un comando de ejecución que produzca mucha salida y tarde mucho tiempo en ejecutarse (> 30 minutos). Estaba pensando en usar subprocess.Popen para hacerlo. Necesito capturar la salida del comando, así que paso PIPE a stdout y stderr.

Un problema de interbloqueo al usar Popen.wait () está bien documentado en muchos foros, por lo que Popen.communicate () es la forma propuesta de evitar el interbloqueo. El problema con esa solución es que los bloques se comunican () hasta que se completa el comando. Necesito imprimir todo lo que llega en la salida estándar mientras se ejecuta el comando. Si no hay salida después de 20 minutos, la ejecución del script será cancelada.

Aquí hay algunas restricciones que debo respetar:

  • Mi versión de Python es 2.4.2 y no puedo actualizar.
  • Si la solución aún es usar subproceso, debo pasar subprocess.PIPE a todos los controladores estándar para evitar este error: http://bugs.python.org/issue1124861

¿Hay una manera de hacerlo?



Para evitar que los almacenamientos intermedios de tuberías se llenen, simplemente inicie un subproceso en segundo plano en el proceso principal. Ese hilo puede leerse continuamente desde stdout (y stderr) para evitar que se llenen los búferes de la tubería, o puede invocar se communicate() . De cualquier manera, el subproceso principal es libre de continuar con el procesamiento normal y el proceso secundario no se bloqueará en una operación de salida.

Convertir una operación de E / S síncrona en una asincrónica (desde el punto de vista del subproceso principal) es uno de los mejores casos de uso para subprocesos. Incluso los marcos asíncronos como Twisted a veces lo utilizarán como una solución de último recurso cuando no haya disponible una interfaz asíncrona nativa para una operación determinada.



Podría considerar el uso de múltiples hilos. Asigne un hilo para leer desde stdout, uno desde stderr, y use un tercer hilo para detectar el tiempo de espera:

while time.time() - last_output_time < 20 * 60: time.sleep( 20 * 60 - (time.time() - last_output_time) ) print ''No output detected in the last 20 minutes. Terminating execution'' sys.exit(1)


import os from subprocess import PIPE, STDOUT, Popen lines = [] p = Popen(cmd, bufsize=1, stdin=open(os.devnull), stdout=PIPE, stderr=STDOUT) for line in iter(p.stdout.readline, ''''): print line, # print to stdout immediately lines.append(line) # capture for later p.stdout.close() p.wait()