Подпроцесс Python. Popen erroring с OSError: [Errno 12] не Может выделить память после промежутка времени

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

10
задан Community 23 May 2017 в 12:00
поделиться

8 ответов

при использовании popen вам нужно передать close_fds = True, если вы хотите, чтобы он закрыл лишние дескрипторы файлов.

создание нового канала, которое происходит в функции _get_handles из обратной трассировки, создает 2 файловых дескриптора, но ваш текущий код никогда не закрывает их, и вы в конечном итоге достигаете предела max fd вашей системы.

Не знаю, почему ошибка, которую вы получаете, указывает на нехватку памяти: это должна быть ошибка дескриптора файла, поскольку возвращаемое значение pipe () содержит код ошибки для этой проблемы.

3
ответ дан 3 December 2019 в 22:38
поделиться

Возможно, вам захочется дождаться завершения всех этих процессов PS, прежде чем добавлять пространство подкачки.

Совершенно не ясно, что означает «выполнение в фоновом режиме, выполняющееся каждые 60 секунд» .

Но ваш вызов subprocess.Popen каждый раз разветвляет новый процесс.

Обновление .

Я предполагаю, что вы каким-то образом оставляете все эти процессы запущенными или зависаете в состоянии зомби. Однако метод связи должен очищать порожденные подпроцессы.

1
ответ дан 3 December 2019 в 22:38
поделиться

Я не думаю, что обстоятельства, приведенные в статье Zenoss, на которую вы ссылаетесь, являются единственной причиной этого сообщения, поэтому еще не ясно, определенно проблема в пространстве подкачки. Я бы посоветовал регистрировать дополнительную информацию даже об успешных вызовах, чтобы вы могли видеть состояние свободной памяти каждый раз непосредственно перед вызовом ps .

Еще одна вещь - если вы укажете ] shell = True в вызове Popen, видите ли вы другое поведение?

Обновление: Если не память, то следующей возможной причиной действительно являются дескрипторы файлов. Я бы посоветовал выполнить команду с ошибкой под strace , чтобы точно увидеть, какие системные вызовы не работают.

0
ответ дан 3 December 2019 в 22:38
поделиться

Этот ответ о пространстве подкачки - подделка. Исторически системы Unix хотели, чтобы пространство подкачки было таким доступным, но они больше так не работают (а Linux никогда не работал таким образом). Вы даже не приблизились к исчерпанию памяти, так что это вряд ли реальная проблема - у вас заканчивается какой-то другой ограниченный ресурс.

Учитывая, где происходит ошибка (_get_handles вызывает os.pipe () для создания трубы к дочернему), единственная реальная проблема, с которой вы можете столкнуться, - это нехватка свободных файловых дескрипторов. Вместо этого я бы поискал незакрытые файлы (lsof -p в PID процесса, выполняющего popen). Если вашей программе действительно необходимо держать много файлов открытыми одновременно, увеличьте лимит пользователей и / или системный лимит для открытых файловых дескрипторов.

3
ответ дан 3 December 2019 в 22:38
поделиться

Возможно, у вас есть утечка памяти, ограниченная некоторым ограничением ресурсов ( RLIMIT_DATA , RLIMIT_AS ?), Унаследованным вашим скрипт на Python. Проверьте свои * ulimit (1) * s перед запуском сценария и профилируйте использование памяти сценарием, как предлагали другие.

Что вы делаете с переменной ps после фрагмента кода, который вы показываете нас? Вы сохраняете ссылку на него, чтобы никогда не быть освобожденным? Цитата из подпроцесса , документация модуля :

Примечание: Считанные данные буферизуются в памяти, поэтому не используйте это метод, если размер данных большой или неограниченный.

... и ps aux могут быть подробными в загруженной системе ...

Обновление

Вы можете проверить rlimits с помощью вашего python скрипт с использованием модуля ресурсов :

import resource
print resource.getrlimit(resource.RLIMIT_DATA) # => (soft_lim, hard_lim)
print resource.getrlimit(resource.RLIMIT_AS)

Если они возвращают "неограниченно" - (- 1, -1) - тогда моя гипотеза неверна, и вы можете двигаться дальше!

См. Также resource.getrusage , особенно. поля ru _ ?? rss , которые могут помочь вам измерить потребление памяти из скрипта python, не обращаясь к внешней программе.

5
ответ дан 3 December 2019 в 22:38
поделиться

Если вы запускаете фоновый процесс, есть вероятность, что вы перенаправили свои процессы на stdin / stdout / stderr.

В этом случае добавьте параметр «close_fds = True» к вашему вызову Popen, который не позволит дочернему процессу унаследовать ваш перенаправленный вывод. Это может быть предел, с которым вы столкнетесь.

2
ответ дан 3 December 2019 в 22:38
поделиться

Наблюдали ли вы за течением времени?

  • lsof
  • ps -aux | grep -i pname
  • top

Все должно давать интересную информацию. Я думаю, что процесс связывает ресурсы, которые необходимо высвободить. Есть ли вероятность, что он связывает дескрипторы ресурсов (блоки памяти, потоки, дескрипторы файлов, дескрипторы потоков или процессов)? stdin, stdout, stderr из порожденного "ps". Дескрипторы памяти ... из множества небольших дополнительных выделений. Мне было бы очень интересно увидеть, что приведенные выше команды отображают для вашего процесса, когда он только что завершил запуск и запустился в первый раз и после 24 часов "сидения" там регулярно запускает подпроцесс.

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

1
ответ дан 3 December 2019 в 22:38
поделиться

Вам необходимо

ps = subprocess.Popen(["sleep", "1000"])
os.waitpid(ps.pid, 0)

, чтобы освободить ресурсы.

Примечание: это не работает в Windows.

0
ответ дан 3 December 2019 в 22:38
поделиться
Другие вопросы по тегам:

Похожие вопросы: