2010-01-14 30 views
3

使用subprocess.Popen.communicate()時出現了一個奇怪的問題。爲了背景,我想從我的python腳本執行一個應用程序。當我在命令行中運行這個程序,我不喜歡這樣(UNIX):subprocess.Popen.communciate()與標準輸入的斷開的管道

 
$ echo "input text" | /path/to/myapp 

從我的劇本,我也希望通過管道輸入到應用程序。所以,我嘗試了以下。但我得到一個「破管道」錯誤,當我嘗試發送的輸入與溝通():

 
>>> cmd = ['/path/to/myapp'] 
>>> p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, stdin=subprocess.PIPE) 
>>> out,err = p.communicate('input text') 
Traceback (most recent call last): 
    File "", line 1, in 
    File "/usr/lib/python2.5/subprocess.py", line 670, in communicate 
    return self._communicate(input) 
    File "/usr/lib/python2.5/subprocess.py", line 1223, in _communicate 
    bytes_written = self._write_no_intr(self.stdin.fileno(), buffer(input, input_offset, 512)) 
    File "/usr/lib/python2.5/subprocess.py", line 1003, in _write_no_intr 
    return os.write(fd, s) 
OSError: [Errno 32] Broken pipe 

爲了使問題陌生人,如果我離開了輸入數據,我沒有得到任何錯誤。但是,這不是一個很好的解決方法,因爲應用程序需要輸入才能工作。

 
>>> p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, stdin=subprocess.PIPE) 
>>> out,err = p.communicate() 
>>> print out 
[error from myapp regarding lack of input] 

任何想法我失蹤了?

回答

3

您的觀察表明myapp正在終止而不讀取(所有)輸入。不知道有關的myapp什麼,這是很難確認,但考慮到例如

$ echo 'hello world' | tr 'l' 'L' 
heLLo worLd 
現在

...:

>>> cmd = ['/usr/bin/tr'] 
>>> p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, stdin=subprocess.PIPE) 
>>> out,err = p.communicate('hello world') 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
    File "/usr/lib/python2.5/subprocess.py", line 668, in communicate 
    return self._communicate(input) 
    File "/usr/lib/python2.5/subprocess.py", line 1218, in _communicate 
    bytes_written = self._write_no_intr(self.stdin.fileno(), buffer(input, input_offset, 512)) 
    File "/usr/lib/python2.5/subprocess.py", line 997, in _write_no_intr 
    return os.write(fd, s) 
OSError: [Errno 32] Broken pipe 

因爲...:

>>> p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stdin=subprocess.PIPE) 
>>> /usr/bin/tr: missing operand 
Try `/usr/bin/tr --help' for more information. 

,如果我們修復該錯誤:

>>> cmd = ['/usr/bin/tr', 'l', 'L'] 
>>> p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stdin=subprocess.PIPE) 
>>> out,err = p.communicate('hello world')>>> print out 
heLLo worLd 
>>> print err 
None 

...它修復了一切G。如果您省略stderr重定向會發生什麼情況 - 您是否會看到myapp中的任何錯誤消息...?

+0

我可以重現這一點,對於2.6上的足夠大的輸入(例如'communicate('foo \ n'* 100000)'),而不是2.7。溝通()對EPIPE的處理是否已更改? –

+1

是的,在2.7和3.1中:http://bugs.python.org/issue10963 –

相關問題