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

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

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

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.Popen "OSError: [Errno 12] Невозможно выделить память" Это дает базовый диагноз и предлагает некоторое обходное решение, например, размножение script и т.д...

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

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

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

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

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

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

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

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

Ответ 1

Если у вас закончилась нехватка памяти, вы можете увеличить свою память подкачки. Или у вас вообще нет возможности свопа. В 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 

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

Ответ 3

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