У меня есть программа, которая обрабатывает несколько файлов, и для каждого файла создается отчет. Часть создания отчета - это отдельная функция, которая принимает имя файла, а затем возвращает. Во время генерации отчета промежуточные части кэшируются в памяти, так как они могут использоваться для нескольких частей отчета, чтобы избежать пересчета.
Когда я запускаю эту программу для всех файлов в каталоге, она будет работать некоторое время, а затем завершится с ошибкой MemoryError. Если я затем перезапущу его в том же каталоге, он пропустит все файлы, для которых был успешно создан отчет, и продолжит работу. Он обработает пару файлов перед тем, как снова произойдет сбой.
Теперь, почему не все ресурсы очищены или помечены хотя бы для сбора мусора после вызова метода, который генерирует отчет? Не осталось никаких экземпляров, и я не использую никаких глобальных объектов, и после каждой обработки файлов все открытые файлы закрываются.
Есть ли способы для меня, чтобы убедиться, что нет никаких дополнительных ссылок на объект? Есть ли способ заставить сборщик мусора в Python?
Немного подробнее о реализации и кеше. Каждый отчет содержит несколько элементов, каждый из которых может опираться на разные вычисления, каждое вычисление может зависеть от других вычислений. Если одно вычисление уже выполнено, я не хочу делать это снова (большинство из них дорогие).
Вот сокращенная версия кэша:
class MathCache:
def __init__(self): self.cache = {}
def get(data_provider):
if not data_provider.id in self.cache:
self.cache[data_provider.id] = data_provider.get_value(self)
return self.cache[data_provider.id]
Экземпляр этого создается, а затем передается каждому элементу в отчете. Этот экземпляр хранится только в локальной ссылке в методе создания отчета.
Все data_providers наследуются от общего класса, который служит для создания уникального идентификатора для экземпляра на основе аргументов конструктора и имени класса. Я передаю MathCache, так как сам data_provider может полагаться на другие вычисления.