在Python中替换subprocess.PIPE?

时间:2015-11-11 11:25:01

标签: python python-2.7 python-3.x

我正在使用子进程模块与linux命令的输出进行交互。下面是我的代码。

import subprocess
import sys

file_name = 'myfile.txt'
p = subprocess.Popen("grep \"SYSTEM CONTROLLER\" "+ file_name, stdout=subprocess.PIPE, shell=True)
(output, err) = p.communicate()
print output.strip()

p = subprocess.Popen("grep \"controller\|worker\" "+ file_name, stdout=subprocess.PIPE, shell=True)
(output, err) = p.communicate()
lines = output.rstrip().split("\n")
print lines

我的程序在执行第二个子进程时挂起,即

p = subprocess.Popen("grep \"controller\|worker\""+ file_name,stdout=subprocess.PIPE, shell=True)

我知道进程挂起的原因是缓冲区重定向到subprocess.PIPE正在填充,这会阻止进程进一步写入。

我想知道是否有办法避免缓冲区已满,以便我的程序继续执行而不会出现任何挂起问题?

2 个答案:

答案 0 :(得分:3)

正如https://docs.python.org/3/library/subprocess.html#subprocess.Popen.communicate所述:

  

注意:读取的数据缓冲在内存中,因此请勿使用此方法   如果数据大小很大或无限制。

相反,请使用file objects读取生成的文本:

output = p.stdout.read()

只要在您阅读时没有其他管道(例如stderr)填满,该过程就不会被阻止。

答案 1 :(得分:3)

实际问题是模式和文件名之间缺少空格,因此grep等待标准输入(stdin)的输入。

"缓冲区已满" .communicate()不易受影响)或p.stdout.read()(它不会修复任何内容:它会将输出加载到内存中,而不像{{ 1}}如果使用多个管道则失败)这里是红鲱鱼。

删除.communicate()并使用命令的list参数:

shell=True