example - subprocess python español
Python Popen: escribir en stdout AND log file simultáneamente (3)
Estoy usando Popen para llamar a un script de shell que está continuamente escribiendo su stdout y stderr en un archivo de registro. ¿Hay alguna forma de generar simultáneamente el archivo de registro de forma continua (hacia la pantalla), o alternativamente, hacer que el script de shell escriba tanto en el archivo de registro como en la salida estándar al mismo tiempo?
Básicamente quiero hacer algo como esto en Python:
cat file 2>&1 | tee -a logfile #"cat file" will be replaced with some script
Nuevamente, esto canaliza stderr / stdout juntos a tee, que lo escribe tanto en stdout como en mi archivo de registro.
Sé cómo escribir stdout y stderr en un archivo de registro en Python. Donde estoy atascado es cómo duplicar estos de nuevo a la pantalla:
subprocess.Popen("cat file", shell=True, stdout=logfile, stderr=logfile)
Por supuesto, podría hacer algo como esto, pero ¿hay alguna forma de hacerlo sin la redirección del descriptor de archivo de tipo tee y shell ?:
subprocess.Popen("cat file 2>&1 | tee -a logfile", shell=True)
Para emular: subprocess.call("command 2>&1 | tee -a logfile", shell=True)
sin invocar el comando tee
:
#!/usr/bin/env python2
from subprocess import Popen, PIPE, STDOUT
p = Popen("command", stdout=PIPE, stderr=STDOUT, bufsize=1)
with p.stdout, open(''logfile'', ''ab'') as file:
for line in iter(p.stdout.readline, b''''):
print line, #NOTE: the comma prevents duplicate newlines (softspace hack)
file.write(line)
p.wait()
Para solucionar posibles problemas de almacenamiento en búfer (si la salida se retrasa), vea los enlaces en Python: lea la entrada de transmisión desde subprocess.communicate () .
Aquí está la versión de Python 3:
#!/usr/bin/env python3
import sys
from subprocess import Popen, PIPE, STDOUT
with Popen("command", stdout=PIPE, stderr=STDOUT, bufsize=1) as p, /
open(''logfile'', ''ab'') as file:
for line in p.stdout: # b''/n''-separated lines
sys.stdout.buffer.write(line) # pass bytes as is
file.write(line)
Puede usar una canalización para leer los datos de la salida estándar del programa y escribirlos en todos los lugares que desee:
import sys
import subprocess
logfile = open(''logfile'', ''w'')
proc=subprocess.Popen([''cat'', ''file''], stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
for line in proc.stdout:
sys.stdout.write(line)
logfile.write(line)
proc.wait()
ACTUALIZAR
En Python 3, el parámetro universal_newlines
controla cómo se utilizan las tuberías. Si es False
, pipe lee los objetos de bytes
retorno y es posible que deba decodificarse (por ejemplo, line.decode(''utf-8'')
) para obtener una cadena. Si es True
, Python hace la decodificación por ti.
Cambiado en la versión 3.3: Cuando universal_newlines es True, la clase usa la codificación locale.getpreferredencoding (False) en lugar de locale.getpreferredencoding (). Consulte la clase io.TextIOWrapper para obtener más información sobre este cambio.
Escribir byte byte terminal para aplicaciones interactivas.
He encontrado que esto simula el comportamiento de tee
más estrechamente para aplicaciones interactivas.
test.py:
#!/usr/bin/env python3
import os
import subprocess
import sys
with subprocess.Popen(sys.argv[1:], stdout=subprocess.PIPE, stderr=subprocess.STDOUT) as proc, /
open(''logfile.txt'', ''bw'') as logfile:
while True:
byte = proc.stdout.read(1)
if byte:
sys.stdout.buffer.write(byte)
sys.stdout.flush()
logfile.write(byte)
else:
break
# In case you need it.
exit_status = proc.returncode
Por ejemplo, si ejecuta:
./test.py bash
luego, los caracteres que escribe aparecen inmediatamente en el terminal a medida que los escribe, lo cual es muy importante para las aplicaciones interactivas. Esto es lo que pasa cuando corres:
bash | tee logfile.txt
Además, si desea que la salida se muestre en el archivo de salida inmediatamente, también puede agregar un:
logfile.flush()
pero tee
no hace esto, y me temo que mataría el rendimiento. Puedes probar esto fácilmente con:
tail -f logfile.txt