Как я прохожу через большой набор данных в python, не получая MemoryError?

У меня есть большая серия растровых наборов данных, отражающих месячные осадки на протяжении нескольких десятилетий. Я написал script в Python, который пересекает каждый растровый файл и делает следующее:

  • Преобразует растр в массив с маской размером,
  • Выполняет множество алгебр массива для расчета нового уровня воды,
  • Записывает результат в выходной растровый файл.
  • Повторы

script - это просто длинный список уравнений алгебры массивов, заключенный в оператор цикла.

Все работает хорошо, если я просто запустил script на небольшой части моих данных (скажем, на 20 лет), но если я попытаюсь обработать всю партию, я получаю MemoryError. Ошибка не дает больше информации, чем эта (за исключением того, что она выделяет строку в коде, в котором Python отказался).

К сожалению, я не могу легко обрабатывать свои данные в кусках - мне действительно нужно иметь возможность делать всю партию сразу. Это связано с тем, что в конце каждой итерации выход (уровень воды) возвращается в следующую итерацию в качестве начальной точки.

Мое понимание программирования в настоящее время очень простое, но я думал, что все мои объекты будут просто перезаписаны в каждом цикле. Я (глупо?) Предположил, что если код удалось успешно выполнить цикл, тогда он должен иметь возможность циклически работать без использования все большего количества памяти.

Я пробовал читать различные фрагменты документации и обнаружил что-то под названием "Сборщик мусора", но мне кажется, что я выхожу из своей глубины, и мой мозг тает! Может ли кто-нибудь дать общее представление о том, что на самом деле происходит с объектами в памяти, когда мой цикл кода? Есть ли способ освобождения памяти в конце каждого цикла или есть еще какой-то "питонический" способ кодирования, который вообще избегает этой проблемы?

Ответ 1

Вам не нужно беспокоиться о себе с управлением памятью, особенно с сборщиком мусора, который имеет очень специфическую задачу, которую вы, скорее всего, даже не используете. Python всегда будет собирать память, которую он может использовать, и повторно использовать.

Есть две причины для вашей проблемы: либо данные, которые вы пытаетесь загрузить, слишком много, чтобы вписаться в память, либо ваши расчеты хранят данные где-то (список, dict, что-то постоянное между итерациями), и это хранилище растет и растет. Профилировщики памяти могут помочь найти это.

Ответ 2

быстрый способ "принудительно" сборщика мусора для очистки временных объектов только для цикла - это оператор del:

for obj in list_of_obj:   
    data = obj.getData()  
    do_stuff(data)   
    del data 

это заставляет интерпретатор удалять и освобождать временные объекты. ПРИМЕЧАНИЕ. Это не гарантирует, что программа не течет или не потребляет память в других частях вычислений, это просто проверка