subprocess.Popen.communicate对大数据集不起作用?

时间:2014-07-24 13:00:02

标签: python linux shell bash

我理解communication()将等待进程完成,将数据存储在内存缓冲区并返回。我认为下面的代码效率不高,因为我想查询所有有趣的rpms并收集每个代码的信息。这将在一台服务器上涉及约15转/每分钟,一组中最多200台服务器。

我想查询Linux中的RPM数据库并从每个.rpm中获取信息并存储它。

在Linux中我会这样做:

rpm -qa --qf '%{NAME} %{VERSION} %{RELEASE}\n' | grep this

我可以使用所有--queryformat RPM提供的。

所以我在Python中有这个功能。但我想简单化。

def getrpms():
queryall = []
rpmqa = subprocess.Popen(['rpm', '-qa'], stdout=subprocess.PIPE,)
grep = subprocess.Popen(['grep', 'stuff'], stdin=rpmqa.stdout, stdout=subprocess.PIPE,)
sort = subprocess.Popen(['sort', '-r'], stdin=grep.stdout, stdout=subprocess.PIPE,)
end_of_pipe = sort.stdout

for line in end_of_pipe:
    queryall.append(line.strip())
return queryall

def rpminfo():
for rpm in getrpms():
    command = "rpm -qi {} ".format(rpm)
    args = shlex.split(command)
    p = subprocess.Popen(args, stdout=subprocess.PIPE)
    pl = p.communicate()    # returns a tuple
    print pl

如何才能提高效率?我看到我可以使用线程和流,但我不知道如何。

1 个答案:

答案 0 :(得分:0)

  

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

在这种情况下,“大”是模糊的,但它往往意味着多兆字节,如果不是更多。单个RPM的rpm -qi输出应该远远不是那么大。我不担心这里的效率。

除此之外,没有必要将命令行构建为单个字符串,只是为了再次拆分它。建立一个列表开始:

p = subprocess.Popen(['rpm', '-qi', rpm, stdout=subprocess.PIPE)

为避免构建所有RPM(匹配stuff)的大型内存列表,请改为使getrpms()成为生成器。这样,您不必一次读取子进程中的所有文本行;你可以一次阅读和处理一行。

def getrpms():
    rpmqa = subprocess.Popen(['rpm', '-qa'], stdout=subprocess.PIPE)
    grep = subprocess.Popen(['grep', 'stuff'], stdin=rpmqa.stdout, stdout=subprocess.PIPE)
    sort = subprocess.Popen(['sort', '-r'], stdin=grep.stdout, stdout=subprocess.PIPE,)

    for line in sort.stdout:
        yield line