2015-09-21 54 views
1

我的Python代碼如下所示:爲什麼我寫入python子流程stdin管道時數據丟失?

def test(): 
    pipe = sp.Popen(["test.sh"], stdin=sp.PIPE) 
    data = "".join([chr((s)%17) for s in range(0,33)]) 
    os.write(pipe.stdin.fileno(), data) 
    pipe.stdin.write("endoffile") 

if __name__ == "__main__": 
    test() 

它調用下面簡單的bash shell腳本,它只是將標準輸入到一個文件中(腳本調用test.sh)

#!/bin/bash 
VALUE=$(cat) 

echo "$VALUE" >> /tmp/test.txt 

當我運行Python代碼我期待的test.txt包含的值0x01..0x10兩次,之後字符串「endoffile」

然而,這裏的文件的hexdump都:

0000000: 0102 0304 0506 0708 090a 0b0c 0d0e 0f10 ................ 
0000010: 0102 0304 0506 0708 090a 0b0c 0d0e 0f65 ...............e 
0000020: 6e64 6f66 6669 6c65 0a     ndoffile. 

看起來,一個字節丟失(0x10)。

我在這裏錯過了什麼?

---更新

改變測試()函數:

def test(): 
    pipe = sp.Popen(["test.sh"], stdin=sp.PIPE) 
    data = "".join([chr((s)%16+1) for s in range(0,32)]) 
    os.write(pipe.stdin.fileno(), data) 
    pipe.stdin.write("endoffile") 

似乎解決。 它似乎與chr(0)發送到管道有關。

回答

1

range()是右側排他性的。

range(0, 33)[0, ..., 32],可能是因爲這樣,你可以不range(0, len(sequence))關閉接一個錯誤。

由於32 % 17 == 15 == 0x0f,您期望的字節'\x10'從來不是列表中的一部分。

編輯1: 從輸出中還缺少零個字符'\x00'。如果使用VALUE=$(cat),則cat的輸出將由shell處理。

SingleUnix/POSIX似乎對此事保持沉默。然而,很明顯,你不能將作爲shell變量的值(或名稱)的一部分,因爲Unix環境要求兩者都是C-style zero terminated strings。實際上我預計VALUE的值是一個空字符串。

編輯2 一些挖後,我可以說,至少ash implementation忽略'\0'處理反引號提供的輸入。輸入被讀取直到EOF和空字符被顯式跳過。

bash確實是一樣的,甚至有一個明確的(即使被註釋掉)與事件相關聯的warning

+0

dhke - 你是對的,但是錯誤的是另一方 - 缺少一個條目。 我懷疑這是由於通過管道發送chr(0) - 它被丟棄。任何想法爲什麼? – oferlivny

+0

@sferic我甚至沒有意識到'\ 0'也沒有,謝謝你提醒我。請參閱編輯。 – dhke

+0

在這個人爲的例子中,test.sh包含一行代碼:'cat >> /tmp/test.txt'。 –