Как я прохожу через большой набор данных в 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
это заставляет интерпретатор удалять и освобождать временные объекты. ПРИМЕЧАНИЕ. Это не гарантирует, что программа не течет или не потребляет память в других частях вычислений, это просто проверка