Альтернативы Python Popen.общаться() ограничения памяти?

у меня есть следующий кусок кода Python (работает v2.7) это приводит к 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 для запуска команды, которая передает гигабайты данных в stdout?

Я должен отметить, что мне нужно обрабатывать потоки вывода и ошибок.

2 ответов


Я думаю, что нашел решение:

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 настолько беден в чем-то, что скрипты оболочки могут делать так легко!


что я, вероятно, сделал бы вместо этого, если бы мне нужно было прочитать 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)

Edit: Если вам нужно потоковое, вы можете попробовать сделать файловый объект и передать его в stdout и stderr. (Хотя я не пробовал.) Затем вы можете прочитать (запрос) из объекта по мере его записи.