español - Python: lee la entrada de transmisión desde subprocess.communicate()
subprocess python español (6)
Creo que la forma más simple de recopilar resultados de un proceso en forma de transmisión es así:
import sys
from subprocess import *
proc = Popen(''ls'', shell=True, stdout=PIPE)
while True:
data = proc.stdout.readline() # Alternatively proc.stdout.read(1024)
if len(data) == 0:
break
sys.stdout.write(data) # sys.stdout.buffer.write(data) on Python 3.x
La función readline()
o read()
solo debe devolver una cadena vacía en EOF, después de que el proceso haya finalizado; de lo contrario, bloqueará si no hay nada que leer ( readline()
incluye la nueva línea, así que en líneas vacías, regresa " /norte"). Esto evita la necesidad de una llamada de communicate()
final incómoda communicate()
después del ciclo.
En los archivos con líneas muy largas, la read()
puede ser preferible para reducir el uso máximo de memoria: el número que se pasa es arbitrario, pero excluirlo da como resultado la lectura de la salida completa de la tubería a la vez, lo que probablemente no sea deseable.
Estoy usando el subprocess.communicate()
Python para leer stdout de un proceso que se ejecuta durante aproximadamente un minuto.
¿Cómo puedo imprimir cada línea de la salida estándar de ese proceso de forma continua, de modo que pueda ver la salida tal como se genera, pero todavía bloquear el proceso antes de continuar?
subprocess.communicate()
parece dar todos los resultados a la vez.
Para obtener el subproceso ''salida línea por línea tan pronto como el subproceso vacía su buffer stdout:
#!/usr/bin/env python2
from subprocess import Popen, PIPE
p = Popen(["cmd", "arg1"], stdout=PIPE, bufsize=1)
with p.stdout:
for line in iter(p.stdout.readline, b''''):
print line,
p.wait() # wait for the subprocess to exit
iter()
se usa para leer líneas tan pronto como se escriben para solucionar el error de lectura anticipada en Python 2 .
Si el subproceso ''stdout utiliza un almacenamiento en búfer en lugar de un almacenamiento intermedio en modo no interactivo (lo que provoca un retraso en la salida hasta que el niño esté lleno o enjuagado explícitamente por el niño), puede intentar forzar una salida sin búfer usando pexpect
, pty
modules o stdbuf
, stdbuf
, script
utilities , ver P: ¿Por qué no usar un pipe (popen ())?
Aquí está el código de Python 3:
#!/usr/bin/env python3
from subprocess import Popen, PIPE
with Popen(["cmd", "arg1"], stdout=PIPE, bufsize=1, universal_newlines=True) as p:
for line in p.stdout:
print(line, end='''')
Nota: A diferencia de Python 2, que da como salida las cadenas de bytes del subproceso; Python 3 usa el modo de texto (la salida de cmd se decodifica utilizando la locale.getpreferredencoding(False)
).
Si desea un enfoque no bloqueante, no use process.communicate()
. Si configura el subprocess.Popen()
argumento stdout
en PIPE
, puede leer process.stdout
y verificar si el proceso aún se ejecuta con process.poll()
.
Si simplemente está tratando de pasar la salida en tiempo real, es difícil ser más simple que esto:
import subprocess
# This will raise a CalledProcessError if the program return a nonzero code.
# You can use call() instead if you don''t care about that case.
subprocess.check_call([''ls'', ''-l''])
Consulte los documentos para subprocess.check_call () .
Si necesita procesar la salida, seguro, bucleela. Pero si no lo haces, solo mantenlo simple.
Editar: JF Sebastian señala que los valores predeterminados para los parámetros stdout y stderr pasan a sys.stdout y sys.stderr, y que esto fallará si sys.stdout y sys.stderr han sido reemplazados (por ejemplo, para capturar salida en pruebas).
Tenga en cuenta que creo que el método de JF Sebastian (a continuación) es mejor.
Aquí hay un ejemplo simple (sin verificación de errores):
import subprocess
proc = subprocess.Popen(''ls'',
shell=True,
stdout=subprocess.PIPE,
)
while proc.poll() is None:
output = proc.stdout.readline()
print output,
Si ls
termina demasiado rápido, entonces el ciclo while puede finalizar antes de haber leído todos los datos.
Puede capturar el resto en stdout de esta manera:
output = proc.communicate()[0]
print output,
myCommand="ls -l"
cmd=myCommand.split()
# "universal newline support" This will cause to interpret /n, /r/n and /r equally, each as a newline.
p = subprocess.Popen(cmd, stderr=subprocess.PIPE, universal_newlines=True)
while True:
print(p.stderr.readline().rstrip(''/r/n''))