python - guia - Ejecutar subproceso e imprimir salida al registro
qgis manual (2)
Estoy seguro de que existe la forma de hacerlo sin crear un archivo temporal para almacenar la salida del proceso
Simplemente debe verificar la documentación de Popen
, en particular sobre stdout
y stderr
:
stdin
,stdout
ystderr
especifican la entrada estándar del programa ejecutado, la salida estándar y los identificadores de archivo de error estándar, respectivamente. Los valores válidos sonPIPE
, un descriptor de archivo existente (un entero positivo), un objeto de archivo existente yNone
.PIPE
indica que se debe crear una nueva canalización para el hijo. Con la configuración predeterminada deNone
, no se producirá ninguna redirección; los manejadores de archivos del niño serán heredados de los padres. Además,stderr
puede serSTDOUT
, lo que indica que los datosstderr
del proceso hijo deben capturarse en el mismo identificador de archivo que parastdout
.
Así que puede ver que puede usar un objeto de archivo o el valor PIPE
. Esto le permite utilizar el método de communicate()
para recuperar la salida:
from StringIO import StringIO
process = subprocess.Popen(arguments, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
output, error = process.communicate()
log_subprocess_output(StringIO(output))
Reescribiría tu código como:
import shlex
import logging
import subprocess
from StringIO import StringIO
def run_shell_command(command_line):
command_line_args = shlex.split(command_line)
logging.info(''Subprocess: "'' + command_line + ''"'')
try:
command_line_process = subprocess.Popen(
command_line_args,
stdout=subprocess.PIPE,
stderr=subprocess.STDOUT,
)
process_output, _ = command_line_process.communicate()
# process_output is now a string, not a file,
# you may want to do:
# process_output = StringIO(process_output)
log_subprocess_output(process_output)
except (OSError, CalledProcessError) as exception:
logging.info(''Exception occured: '' + str(exception))
logging.info(''Subprocess failed'')
return False
else:
# no exception was raised
logging.info(''Subprocess finished'')
return True
Estoy buscando la manera de llamar shell scripts desde python y escribir su stdout y stderr a un archivo utilizando el registro. Aquí está mi código:
import logging
import tempfile
import shlex
import os
def run_shell_command(command_line):
command_line_args = shlex.split(command_line)
logging.info(''Subprocess: /"'' + command_line + ''/"'')
process_succeeded = True
try:
process_output_filename = tempfile.mktemp(suffix = ''subprocess_tmp_file_'')
process_output = open(process_output_filename, ''w'')
command_line_process = subprocess.Popen(command_line_args,/
stdout = process_output,/
stderr = process_output)
command_line_process.wait()
process_output.close()
process_output = open(process_output_filename, ''r'')
log_subprocess_output(process_output)
process_output.close()
os.remove(process_output_filename)
except:
exception = sys.exc_info()[1]
logging.info(''Exception occured: '' + str(exception))
process_succeeded = False
if process_succeeded:
logging.info(''Subprocess finished'')
else:
logging.info(''Subprocess failed'')
return process_succeeded
Y estoy seguro de que existe la forma de hacerlo sin crear un archivo temporal para almacenar la salida del proceso. ¿Algunas ideas?
Puede intentar pasar la tubería directamente sin almacenar en memoria intermedia toda la salida del subproceso en la memoria:
from subprocess import Popen, PIPE, STDOUT
process = Popen(command_line_args, stdout=PIPE, stderr=STDOUT)
with process.stdout:
log_subprocess_output(process.stdout)
exitcode = process.wait() # 0 means success
donde log_subprocess_output()
podría verse así:
def log_subprocess_output(pipe):
for line in iter(pipe.readline, b''''): # b''/n''-separated lines
logging.info(''got line from subprocess: %r'', line)