Python Popen.communicate()内存限制的替代方案?

时间:2011-07-29 23:46:38

标签: python memory stream popen

我有以下大量的Python代码(运行v2.7),当我处理大(几GB)文件时会导致MemoryError异常被抛出:

myProcess = Popen(myCmd, shell=True, stdout=PIPE, stderr=PIPE)
myStdout, myStderr = myProcess.communicate()
sys.stdout.write(myStdout)
if myStderr:
    sys.stderr.write(myStderr)

在阅读documentation to Popen.communicate()时,似乎有一些缓冲:

  

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

是否有办法禁用此缓冲,或强制在进程运行时定期清除缓存?

我应该在Python中使用哪种替代方法来运行将千兆字节数据流式传输到stdout的命令?

我应该注意,我需要处理输出和错误流。

3 个答案:

答案 0 :(得分:6)

我想我找到了一个解决方案:

myProcess = Popen(myCmd, shell=True, stdout=PIPE, stderr=PIPE)
for ln in myProcess.stdout:
    sys.stdout.write(ln)
for ln in myProcess.stderr:
    sys.stderr.write(ln)

这似乎让我的内存使用量下降到足以完成任务。

<强>更新

我最近发现了一种使用threads在Python中处理数据流的更灵活方式。有趣的是,Python在shell脚本可以轻松实现的方面非常糟糕!

答案 1 :(得分:4)

我可能会做的事情,如果我需要读取stdout以获取大的东西,在创建过程时将其发送到文件。

with open(my_large_output_path, 'w') as fo:
    with open(my_large_error_path, 'w') as fe:
        myProcess = Popen(myCmd, shell=True, stdout=fo, stderr=fe)

编辑:如果需要流式传输,可以尝试制作类似文件的对象并将其传递给stdout和stderr。 (尽管如此,我还没试过。)然后你可以在写入时从对象中读取(查询)。

答案 2 :(得分:0)

对于那些在使用 Popen 时应用程序在一定时间后挂起的人,请在下面查看我的案例:

经验法则,如果您不打算使用 stderrstdout 流,则不要传入/初始化它们Popen的参数!因为它们会填满并给您带来很多问题。

如果您在一段时间内需要它们并且需要保持进程运行,那么您可以随时关闭这些流。

try:
    p = Popen(COMMAND, stdout=PIPE, stderr=PIPE)
    # After using stdout and stderr
    p.stdout.close()
    p.stderr.close()
except Exception as e:
    pass