Redirigir el subproceso stderr a stdout


Quiero redirigir la salida stderr de un subproceso a stdout. La constante STDOUT debería hacer eso, ¿no?

Sin embargo,

$ python >/dev/null -c 'import subprocess;\
                        subprocess.call(["ls", "/404"],stderr=subprocess.STDOUT)'

hace salida algo. ¿Por qué es ese el caso, y cómo obtengo el mensaje de error en stdout?

Author: phihag, 2012-07-16

2 answers

Una lectura cercana del código fuente da la respuesta. En particular, la documentación {[8] } es engañosa cuando dice:

subprocess.STDOUT
Valor especial que (...) indica que el error estándar debería entrar en el mismo identificador como salida estándar.

Dado que stdout se establece en "default" (-1, técnicamente) cuando se evalúa stderr=subprocess.STDOUT, stderr también se establece en "default". Desafortunadamente, esto significa que la salida stderr todavía va a stderr.

Para resolver el problema, pase el archivo stdout en lugar de subprocess.STDOUT:

$ python >/dev/null -c 'import subprocess,sys;subprocess.call(["ls", "/404"],
                        stderr=sys.stdout.buffer)'

O, para compatibilidad con legacy 2.x versiones de Python:

$ python >/dev/null -c 'import subprocess,sys;subprocess.call(["ls", "/404"],
                        stderr=sys.stdout.fileno())'
 33
Author: phihag,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-07-16 11:32:09

En realidad, usar subprocess.STDOUT hace exactamente lo que se indica en la documentación: redirige stderr a stdout de modo que, por ejemplo,

proc = subprocess.Popen(self.task["command"], shell=False, bufsize=1, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
output = ""
while (True):
    # Read line from stdout, break if EOF reached, append line to output
    line = proc.stdout.readline()
    line = line.decode()
    if (line == ""): break
    output += line

Resulta en la variable output que contiene la salida del proceso tanto de stdout como de stderr.

stderr=subprocess.STDOUT redirige toda la salida stderr directamente a la salida std del proceso de llamada, que es una diferencia importante.

 8
Author: Maxxim,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-03-15 06:11:22