2012-05-14 35 views
8

我正在Python中運行C可執行文件,並且此可執行文件有時會出現段錯誤。當它發生段錯誤時,子進程模塊不會在stdout或stderr中返回任何內容。Python子流程模塊不會在段錯誤上返回stdout

樣品的編號:

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 

有沒有辦法獲得可執行文件的輸出,即使它崩潰?

將returncode轉換爲字符串消息的一般方法也很好。

回答

2

應用程序在遇到分段錯誤之前幾乎肯定不會刷新其輸出緩衝區。

默認情況下,C stdio庫配置緩衝區爲stdout,以便緩衝區在每一行結束時被刷新,但只有stdout是tty。這就是爲什麼當你從命令行運行a.out時,你看到輸出

你不能直接讓C程序從Python端改變它。但你可以做的是給它一個tty用於它的stdout,即一個僞tty。打開和設置僞終端的細節比設置常規管道複雜得多,但有一些模塊可以幫助您:請參閱Pexpectthis 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 
$ 

返回我的Mac上的代碼是0,令人困惑,因爲對於信號終止的程序沒有返回代碼。

+0

好的解決方案,如果你控制C代碼,並且能夠將'setvbuf'調用加入並重新編譯。我假設修改第三方C代碼是不可能的。 – Celada

+0

那麼,如果你的第三方代碼在它崩潰之前沒有刷新它的stdout,那麼你可以做的事情就不多了。 – vy32