Python Popen.communicate()内存限制的替代方案?
我有一段Python代码(运行在2.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)
在查看关于Popen.communicate()
的文档时,我发现这里面有一些缓冲的处理:
注意 读取的数据会在内存中进行缓冲,所以如果数据量很大或者没有限制,就不要使用这个方法。
有没有办法禁用这个缓冲,或者在进程运行时定期清理缓存呢?
在Python中,我应该使用什么其他方法来运行一个命令,以便将几GB的数据流输出到stdout
?
我还需要处理输出和错误流。
3 个回答
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
5
如果我需要读取这么大一段输出,我可能会选择在创建进程的时候把它发送到一个文件里。
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)
补充一下:如果你需要实时查看输出,可以尝试创建一个像文件一样的对象,然后把它传给标准输出和标准错误输出。(不过我还没试过这个。)这样的话,你就可以在数据写入的同时从这个对象中读取(查询)内容。
8
我想我找到了解决办法:
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)
这个方法似乎能让我减少内存使用,从而顺利完成任务。
更新
我最近发现了一种更灵活的方式来处理Python中的数据流,使用线程。有趣的是,Python在这方面表现得很差,而shell脚本却能轻松做到!