2012-01-27 116 views
3

我試圖從一個目錄grep並限制搜索到前100個結果。下面的代碼保存得Python grep和管道通過Popen

[..] 
grep: writing output: Broken pipe 
grep: writing output: Broken pipe 
grep: writing output: Broken pipe 
grep: writing output: Broken pipe 
[..] 

代碼:

p_grep = Popen(['/bin/bash', '-c', 'grep -F "asdasdasd" data/*'], stdout = PIPE) 
p_head = Popen(['head', '-100'], stdin = p_grep.stdout, stdout = PIPE) 
output = p_head.communicate()[0] 

如何解決呢?

+2

試試這個: http://stackoverflow.com/questions/2595602/pythons-popen-cleanup – xkrz 2012-01-27 21:49:30

+1

@xkrz,是不是他正在做的建議解決方案? – 2012-01-27 21:56:25

+0

你需要執行grep還是僅僅是一個例子?否則,grep有一個--max-count選項,您可以使用而不是通過管道輸出整個輸出。 – GaretJax 2012-01-27 21:58:33

回答

1

其實在這種情況下,你可以這樣做:

output = check_output(['/bin/bash', '-c', 'grep -F "asdasdasd" data/* | head -100']) 
+0

這個問題是,我不知道爲什麼,它執行所有的grepping,然後它通過管道,所以,在shell中只需要幾秒鐘,它需要更長的時間python – pistacchio 2012-01-27 22:11:23

+0

@pistacchio,can您嘗試將'--line-buffered'傳遞給'grep'並查看是否改變了任何內容? – 2012-01-27 22:22:35

+0

我試過,沒有,它不會改變:( – pistacchio 2012-01-27 22:23:52

0

按照Popen documentation on writing pipes你應該確保關閉的管道過程stdout(在這種情況下p_grep),使他們能夠接收SIGPIPE從管道到進程(在這種情況下爲p_head)。

此外,根據this post,爲每個子進程提供一個設置函數非常重要,以便Python的SIGPIPE處理恢復到其默認行爲。

因此,代碼變爲:

def preexec_fn(): 
    import signal 
    signal.signal(signal.SIGPIPE, signal.SIG_DFL) 

p_grep = Popen(['/bin/bash', '-c', 'grep -F "asdasdasd" data/*'], stdout=PIPE, preexec_fn=preexec_fn) 
p_head = Popen(['head', '-100'], stdin=p_grep.stdout, stdout=PIPE, preexec_fn=preexec_fn) 
p_grep.stdout.close() 
output = p_head.communicate()[0] 

這應該引起grep進程終止一次head完成。