example español python subprocess popen

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