2012-05-14 3 views
8

Я запускаю исполняемый файл C из Python, и этот исполняемый файл иногда является segfaults. Когда он отключается, модуль subprocess не возвращает ничего в stdout или stderr.Модуль подпроцесса Python не возвращает stdout на segfault

Пример кода:

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 

Источником a.out является:

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

Выход ./a.out является:

hello world 
Floating point exception 

Вывод кода Python является (в Linux , python 2.7):

out: "" 
err: "" 
-8 

Есть ли способ получить выход исполняемого файла, даже если он сработает?

Общий метод перевода кода возврата в строковое сообщение также будет приятным.

ответ

2

Приложение почти наверняка не промывает свои выходные буферы перед тем, как встретится с ошибкой сегментации.

По умолчанию библиотека C stdio настраивает буферизацию для stdout, так что буферы очищаются на каждом конце строки, но только stdout - это tty. Вот почему вы do смотрите вывод, когда вы запускаете a.out из командной строки.

Вы не можете напрямую изменить программу C со стороны Python. Но то, что вы может сделать это tty использовать для своего stdout, а именно псевдо-tty. Детали открытия и настройки псевдотерминала намного сложнее, чем установка обычного канала, но есть некоторые модули, которые помогут вам: см., Например, Pexpect и this SO question.

3

Ваша программа C не смывает свой выходной буфер. Самый простой способ обойти эту проблему, чтобы изменить режим вывода STDOUT в небуферизован:

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

Теперь программу (которую я отредактированный, чтобы исправить опечатку) производит правильный выход:

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

Возвращение код 0 на моем Mac, смутно, потому что программы, которые завершены для сигнала, не имеют кода возврата.

+0

Хорошее решение, если вы управляете кодом C и можете добавить в него вызов 'setvbuf' и перекомпилировать. Я принимал сторонний C-код, о котором невозможно изменить. – Celada

+0

Ну, если ваш сторонний код не стирает его stdout до того, как он сработает, вы не сможете многое сделать. – vy32

Смежные вопросы