2013-12-20 52 views
0

將大量數據快速寫入C子進程時,出現Broken Pipe錯誤。Python中的C子進程:sub.stdin.write IOError中斷管道

process = subprocess.Popen("./gpiopwm", stdin=subprocess.PIPE) 
while True: 
    process.stdin.write("m2000\n") 
    print "bytes written" 

gpiopwm.c的主迴路的Sectio:

所以我從一個Python腳本運行AC子

printf("1\n"); 
while (1) { 
    fgets(input,7,stdin); // Takes input from python script 
    printf("2\n"); 

    numbers = input+1;  // stores all but first char of input 
    char first = input[0]; // stores first char of input 

    if (first=='m') { 
     printf("3\n"); 
     printf("%s\n",numbers); 
    } 
} 

然而,從這個輸出如下:

1 
bytes written 
Traceback (most recent call last): 
    File "serial-receive-to-pwm.py", line 20, in <module> 
    process.stdin.write("m2000\n") 
IOError: [Errno 32] Broken pipe 

該C程序明顯突破fgets行,如2從不打印。 我做錯了什麼?我怎樣才能避免這種情況?

編輯: 我已更新fgets行,以便它不包括取消引用參數,但仍然收到損壞的管道錯誤。

編輯:如果您嘗試從控制檯上運行你的C程序 input被初始化爲char *input="m2000";

+1

請顯示'input'的完整聲明(以及可能的初始化)。 –

回答

2

,你會看到它崩潰。如果你在一個調試器中運行,你會看到它在這條線:

fgets(*input,7,stdin); 

好像input是一個字符數組,當你取消對它的引用與*input你逝去的不是指針,但單char值。這導致未定義的行爲和崩潰。

如果不是錯誤,那麼該行應該給出您編譯器提供的非常大的警告消息。不要忽視警告信息,它們通常是你做錯事情並且可能危險的指標。


一般提示:當開發一個應該從另一程序調用,就像你在這裏做節目,測試程序首先要確保它的工作原理。如果它不起作用,請先修復它。

最後提示:請記住,fgets包括目標字符串中的換行符。您可能需要檢查它並將其刪除。


有了上次的編輯,顯示input聲明,我們知道真正問題:您正在試圖修改常量數據,並要寫入超出數據的邊界爲好。

當你input指向一個字符串,你要記住,所有的文本字符串只讀,你不能修改文本字符串。試圖這樣做是未定義的行爲。更糟的是,你的字符串只有六個字符長,但你試着寫七個字符。

第一變化的input的聲明和初始化:

char input[16] = "m2000\n"; 

這將聲明爲陣列,位於所述疊層上,並且可以被修改。然後做

while (fgets(input, sizeof(input), stdin) != NULL) { ... } 

這完成兩件事情:一是通過sizeof(input)的大小,你可以肯定的是fgets永遠不會寫出界。其次,通過在循環條件中使用fgets調用,循環將在Python腳本中斷時結束,並且不會循環永遠無法讀取任何內容,然後處理您從未讀過的數據。

+1

這不是很好嗎()**還**明確告訴OP **如何**解決這個問題? ;-) – alk

+0

我已經說過錯誤在fgets行。編譯器工作正常,否則它不會編譯。 – theoB610

+0

@ theoB610:假設'char輸入[至少7];'在此期間試試這個:'fgets(input,7,stdin);' – alk