2012-05-14 7 views
8

Estoy ejecutando un ejecutable C desde Python y este ejecutable a veces se segmenta. Cuando segmenta, el módulo de subproceso no devuelve nada en stdout o stderr.El módulo de subproceso de Python no devuelve stdout en segfault

Código de ejemplo:

import subprocess 

proc = subprocess.Popen(['./a.out'], stdin=subprocess.PIPE, 
     stdout=subprocess.PIPE, stderr=subprocess.PIPE) 
out, err = proc.communicate() 
print 'out: "%s"' % out 
print 'err: "%s"' % err 
print proc.returncode 

La fuente de a.out es:

int main() { 
    printf("hello world\n"); 
    int x = 1/0; 
} 

La salida del ./a.out es:

hello world 
Floating point exception 

La salida del código Python es (en Linux , python 2.7):

out: "" 
err: "" 
-8 

¿Hay alguna forma de obtener la salida del ejecutable incluso si se bloquea?

Un método genérico para traducir el código de retorno a un mensaje de cadena, también sería bueno.

Respuesta

2

La aplicación casi con certeza no está descargando sus búfers de salida antes de que encuentre el error de segmentación.

De forma predeterminada, la biblioteca C stdio configura el almacenamiento en búfer para stdout de modo que los búferes se vacían en cada extremo de la línea, pero solo stdout es un tty. Es por eso que haga vea la salida cuando ejecuta a.out desde la línea de comando.

No se puede hacer directamente que el programa C cambie esto desde el lado de Python. Pero lo que puede hacer es darle un tty para su stdout, es decir, un pseudo tty. Los detalles de abrir y configurar una pseudo terminal son mucho más complicados que configurar una pipa regular, pero hay algunos módulos que lo ayudarán: Consulte Pexpect y this SO question, entre otros.

3

Su programa C no está vaciando su búfer de salida. La forma más fácil de evitar este problema es cambiar el modo de salida de la salida estándar a sin búfer:

#include <stdio.h> 
int main(int argc,char **argv) { 
    setvbuf(stdout,_IONBF,0,0); 
    printf("hello world\n"); 
    int x = 1/0; 
} 

Ahora su programa (que he editado para corregir un error tipográfico) produce la salida correcta:

$ python2.7 x.py 
out: "hello world 
" 
err: "" 
0 
$ 

El regreso el código es 0 en mi Mac, confusamente, porque los programas que se terminan para una señal no tienen un código de retorno.

+0

Buena solución, si controla el código C y puede agregar la llamada 'setvbuf' y volver a compilar. Estaba asumiendo el código C de terceros, que está fuera de cuestión modificar. – Celada

+0

Bueno, si el código de su tercero no elimina su stdout antes de que falle, no hay mucho que pueda hacer. – vy32

Cuestiones relacionadas