Альтернативы ограничениям памяти Python Popen.communicate()?
У меня есть следующий фрагмент кода 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)
При чтении документации к Popen.communicate()
происходит некоторая буферизация:
Примечание Чтение данных буферизируется в памяти, поэтому не используйте этот метод, если размер данных является большим или неограниченным.
Есть ли способ отключить эту буферизацию или заставить кеш очищаться периодически во время процесса?
Какой альтернативный подход я должен использовать в Python для запуска команды, которая передает гигабайты данных в stdout
?
Я должен отметить, что мне нужно обрабатывать выходные и потоки ошибок.
Ответы
Ответ 1
Я думаю, что нашел решение:
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 настолько низок в чем-то, что скрипты оболочки могут делать это легко!
Ответ 2
То, что я бы, вероятно, сделал, вместо этого, если мне нужно было прочитать 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. (Я еще не пробовал это.) Затем вы могли читать (запрос) из объекта, когда он записывается.