2012-01-27 42 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完成。