subprocess.Popen.communicate处理大数据集效率低吗?
我明白 communicate() 这个函数会等进程完成后,才会把数据存储到内存中并返回。我在想下面的代码可能效率不高,因为我想查询所有有趣的 RPM(软件包),并收集每个 RPM 的信息。这涉及到大约 15 个 RPM 在一台服务器上,而我可能需要在一个组里处理多达 200 台服务器。
我想在 Linux 中查询 RPM 数据库,获取每个 .rpm 的信息并存储起来。
在 Linux 中,我会这样做:
rpm -qa --qf '%{NAME} %{VERSION} %{RELEASE}\n' | grep this
而且我可以使用 RPM 提供的所有 --queryformat 选项。
所以我在 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
注意:读取的数据会暂时存储在内存中,所以如果数据量很大或者没有上限,就不要使用这种方法。
这里说的“很大”其实有点模糊,但一般来说是指几个兆字节,甚至更多。对于单个RPM来说,rpm -qi
的输出应该远远达不到这个大小。所以在这里不需要担心效率问题。
另外,没有必要把命令行构建成一个完整的字符串再拆分。可以先构建一个列表:
p = subprocess.Popen(['rpm', '-qi', rpm, stdout=subprocess.PIPE)
为了避免在内存中构建一个包含所有匹配stuff
的RPM的大列表,可以把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