Альтернативы Python Popen.communicate () ограничения памяти? - PullRequest
19 голосов
/ 30 июля 2011

У меня есть следующий фрагмент кода 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 ]

6 голосов
/ 30 июля 2011

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

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, используя threads . Интересно, что Python настолько беден, что сценарии оболочки могут сделать это так легко!

4 голосов
/ 30 июля 2011

Что бы я, вероятно, сделал бы вместо этого, если бы мне нужно было прочитать стандартный вывод для чего-то такого большого, это отправить его в файл при создании процесса., вы можете попробовать создать файловый объект и передать его в stdout и stderr.(Однако я не пробовал этого.) Затем вы могли бы читать (запрашивать) объект, когда он пишется.

...