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

Ale*_*lds 19 python memory stream popen

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

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

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

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

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

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

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

Ale*_*lds 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)
Run Code Online (Sandbox Code Playgroud)

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

更新

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

  • 这忽略了`警告:使用communic()而不是.stdin.write,.stdout.read或.stderr.read,以避免由于任何其他OS管道缓冲区填满并阻止子进程而导致的死锁.文档.它可能会普遍起作用,但是在myProcess.stdout中,对于ln存在死锁的潜在风险:`如果`myProcess.stderr`填满了.我来这里寻找解决方案. (4认同)

Tor*_*ler 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)
Run Code Online (Sandbox Code Playgroud)

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