0

我需要解析由产生大量数据的外部程序(第三方,我无法控制)产生的输出。由于输出的大小大大超过了可用内存,我想在进程运行时解析输出,并从内存中删除已经处理过的数据。

到目前为止,我做了这样的事情:

import subprocess

p_pre = subprocess.Popen("preprocessor",stdout = subprocess.PIPE) 
# preprocessor is an external bash script that produces the input for the third-party software
p_3party = subprocess.Popen("thirdparty",stdin = p_pre.stdout, stdout = subprocess.PIPE)

(data_to_parse,can_be_thrown) = p_3party.communicate()

parsed_data = myparser(data_to_parse)

当“第三方”输出足够小时,这种方法有效。但正如 Python 文档中所述:

读取的数据是缓存在内存中的,所以如果数据量很大或者没有限制,不要使用这种方法。

我认为更好的方法(实际上可以让我节省一些时间)data_to_parse是在生成时开始处理,并且在正确完成解析时“清除”data_to_parse删除已经解析的数据。

我还尝试使用 for 循环,例如:

parsed_data=[]
for i in p_3party.stdout:
    parsed_data.append(myparser(i))

但它卡住了,无法理解为什么。

所以我想知道实现这一目标的最佳方法是什么?有哪些需要注意的问题?

4

2 回答 2

1

您可以使用 subprocess.Popen() 创建一个从中读取行的蒸汽。

import subprocess

stream = subprocess.Popen(stdout=subprocess.PIPE).stdout

for line in stream:
    #parse lines as you recieve them.
    print line

您可以将这些行传递给您的myparser()方法,或者将它们附加到一个列表中,直到您准备好使用它们......无论如何。


在您的情况下,使用两个子流程,它会像这样工作:

import subprocess

def method(stream, retries=3):
    while retries > 0:
        line = stream.readline()
        if line:
            yield line
        else:
            retries -= 1

pre_stream = subprocess.Popen(cmd, stdout=subprocess.PIPE).stdout
stream = subprocess.Popen(cmd, stdin=pre_stream, stdout=subprocess.PIPE).stdout

for parsed in method(stream):
    # do what you want with the parsed data.
    parsed_data.append(parsed)
于 2013-04-03T11:38:17.730 回答
1

像 in 一样迭代文件for i in p_3party.stdout:使用预读缓冲区。该readline()方法使用管道可能更可靠——AFAIK它逐个字符地读取。

while True:
    line = p_3party.stdout.readline()
    if not line:
        break
    parsed_data.append(myparser(line))
于 2013-04-03T11:51:46.623 回答