Imprima constantemente la salida del subproceso mientras el proceso se está ejecutando
Para iniciar programas desde mis scripts de Python, estoy usando el siguiente método:
def execute(command):
process = subprocess.Popen(command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
output = process.communicate()[0]
exitCode = process.returncode
if (exitCode == 0):
return output
else:
raise ProcessException(command, exitCode, output)
Entonces, cuando inicio un proceso como Process.execute("mvn clean install")
, mi programa espera hasta que finaliza el proceso, y solo entonces obtengo el resultado completo de mi programa. Esto es molesto si estoy ejecutando un proceso que tarda un poco en finalizar.
¿Puedo dejar que mi programa escriba la salida del proceso línea por línea, sondeando la salida del proceso antes de que termine en un bucle o algo así?
Encontré este artículo que podría estar relacionado.
Puede usar iter para procesar líneas tan pronto como las genere el comando: lines = iter(fd.readline, "")
. Aquí hay un ejemplo completo que muestra un caso de uso típico (gracias a @jfs por ayudar):
from __future__ import print_function # Only Python 2.x
import subprocess
def execute(cmd):
popen = subprocess.Popen(cmd, stdout=subprocess.PIPE, universal_newlines=True)
for stdout_line in iter(popen.stdout.readline, ""):
yield stdout_line
popen.stdout.close()
return_code = popen.wait()
if return_code:
raise subprocess.CalledProcessError(return_code, cmd)
# Example
for path in execute(["locate", "a"]):
print(path, end="")
Para imprimir la salida del subproceso línea por línea tan pronto como se vacía su buffer de salida estándar en Python 3:
from subprocess import Popen, PIPE, CalledProcessError
with Popen(cmd, stdout=PIPE, bufsize=1, universal_newlines=True) as p:
for line in p.stdout:
print(line, end='') # process line here
if p.returncode != 0:
raise CalledProcessError(p.returncode, p.args)
Aviso: no es necesario p.poll()
: el ciclo finaliza cuando se alcanza eof. Y no es necesario iter(p.stdout.readline, '')
: el error de lectura anticipada se solucionó en Python 3.
Consulte también Python: lea la entrada de transmisión desde subprocess.communicate() .