我有以下大量的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
的命令?
我应该注意,我需要处理输出和错误流。
答案 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 时应用程序在一定时间后挂起的人,请在下面查看我的案例:
经验法则,如果您不打算使用 stderr 和 stdout 流,则不要传入/初始化它们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