python notebook Как избежать[Errno 12] Невозможно выделить ошибки памяти, вызванные использованием модуля подпроцесса




python out of memory exception (3)

Полный рабочий тест

Конечно, в зависимости от вашей памяти на локальных и удаленных компьютерах размеры вашего массива будут разными.

z1 = numpy.random.rand(300000000,2);
for i in range(1000):
  print('*******************************************\n'); 
  direct_output = subprocess.check_output('ssh [email protected] "ls /"', shell=True);
  direct_output = 'a'*1200000; 
  a2 = direct_output*10;
  print(len(direct_output));

Текущий вариант использования

В случае, если это поможет моему случаю использования:

Я выдаю db-запросы, а затем сохраняю полученные таблицы на удаленной машине. Затем я хочу передать их по сети и провести анализ. До сих пор в python я делал что-то вроде следующего:

#run a bunch of queries before hand with the results in remote files

....
counter = 0
mergedDataFrame = None
while NotDone:
  output = subprocess.check_output('ssh [email protected] cat /data/file%08d'%(counter))
  data = pandas.read_csv(...)
  #do lots of analysis, append, merge, numpy stuff etc...
  mergedDataFrame = pandas.merge(...)
  counter += 1

В какой-то момент я получаю следующую ошибку в команде check_output: [Errno 12] Невозможно выделить память

Задний план

Благодаря следующим вопросам я думаю, что у меня есть идея, что не так. Существует ряд решений, и я пытаюсь определить, какое из решений позволит избежать [Errno 12] Невозможно выделить ошибку памяти, связанную с реализацией подпроцесса, используя fork / clone.

Python subprocess.Popen «OSError: [Errno 12] Невозможно выделить память» Это дает базовый диагноз и предлагает некоторое обходное решение, например, размножение отдельного сценария и т. Д. ...

Общие сведения о ошибках размещения вил Python и памяти. Предлагает использовать rfoo для обхода ограничения подпроцесса fork / clone и нереста дочернего процесса и копии памяти и т. Д. Это, по-видимому, подразумевает модель клиент-сервер

Каков самый простой способ использования SSH с помощью Python? , но у меня есть дополнительные ограничения, которые я не могу использовать подпроцесс из-за ограничений памяти и реализации fork / clone? Решения предполагают использование парамико или что-то построенное поверх него, другие предлагают подпроцесс (который, как я нашел, не будет работать в моем случае).

Были и другие подобные вопросы, но в ответах часто говорилось о том, что файловые дескрипторы являются виновниками (в данном случае это не так), добавив в систему больше ОЗУ (я не могу этого сделать), обновление до x64 (я уже нахожусь на x64). Некоторые намекают на проблему ENOMEM. Несколько ответов указывают на попытку определить, не является ли подпроцесс.Popen (в моем случае check_output) неправильной очистки процессов, но похоже, что S. Lott и другие согласны с тем, что сам код подпроцесса правильно очищается.

Я искал исходный код на github https://github.com/paramiko/paramiko/search?q=Popen&type=Code и, похоже, использует подпроцесс в файле proxy.py.

Актуальные вопросы

Означает ли это, что в конечном счете paramiko использует описанное выше решение Popen, которое будет иметь проблемы, когда площадь памяти python растет и повторяющиеся вызовы Popen выполняются из-за реализации клона / вилки?

Если paramiko не будет работать, есть ли другой способ сделать то, что я ищу, с решением только на стороне клиента? Или потребуется решение клиент / сервер / сокет? Если да, то будут ли какие-либо из rfoo, торнадо или zeromq, http-переводы?

Примечания Я использую 64-битную основную память объемом 8 ГБ. Я не хочу выбирать варианты покупки большего объема оперативной памяти.



Если у вас заканчивается память, это, вероятно, потому, что подпроцесс пытается слишком много читать в памяти. Решение, за исключением использования перенаправления на локальный файл, вероятно, использует всплывающие функции с помощью пары stdin / stdout, которую можно читать из-за небольшого количества времени.


Если у вас закончилась нехватка памяти, вы можете увеличить свою память подкачки. Или у вас вообще нет возможности свопа. В Ubuntu (он должен работать и для других дистрибутивов), вы можете проверить свой своп:

$sudo swapon -s

если он пуст, это означает, что у вас нет смены. Чтобы добавить своп 1GB:

$sudo dd if=/dev/zero of=/swapfile bs=1024 count=1024k
$sudo mkswap /swapfile
$sudo swapon /swapfile

Добавьте в fstab следующую строку, чтобы сделать своп постоянным.

$sudo vim /etc/fstab

     /swapfile       none    swap    sw      0       0 

Источник и дополнительную информацию можно найти here .