Ошибка OutOfMemory на полке Python - PullRequest
       16

Ошибка OutOfMemory на полке Python

2 голосов
/ 04 февраля 2010

У меня есть некоторые данные, хранящиеся в БД, которые я хочу обработать.Доступ к БД мучительно медленный, поэтому я решил загрузить все данные в словарь перед любой обработкой.Однако из-за огромного размера хранимых данных я получаю ошибку нехватки памяти (я вижу, что используется более 2 гигабайт).Поэтому я решил использовать структуру данных на диске и обнаружил, что использование полки - это вариант.Вот что я делаю (псевдо-код Python)

def loadData():
    if (#dict exists on disk):
        d = shelve.open(name)
        return d
    else:
        d = shelve.open(name, writeback=True)
        #access DB and write data to dict
        # d[key] = value 
        # or for mutable values
        # oldValue = d[key]
        # newValue = f(oldValue)
        # d[key] = newValue 
        d.close()
        d = shelve.open(name, writeback=True)
        return d

У меня есть пара вопросов,

1) Мне действительно нужен writeBack = True?Что он делает?

2) Я все еще получаю исключение OutofMemory, так как я не контролирую, когда данные записываются на диск.Как я могу это сделать?Я пытался делать sync () каждые несколько итераций, но это тоже не помогло.

Спасибо!

Ответы [ 2 ]

9 голосов
/ 04 февраля 2010

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

Преимущество параметра в том, что с ним вам не нужно нужен искаженный код, который вы показываете в своем комментарии для изменяемых элементов, мутатор которых является методом - просто

shelf['foobar'].append(23)

работает (если shelf был открыт с включенной обратной записью), предполагая, что элемент с ключом 'foobar' является списком, конечно, в то время как это было бы молча без операции (оставляя элемент на диске без изменений), если shelf был открыт без обратной записи - в последнем случае вам действительно нужно кодировать

thelist = shelf['foobar']
thelist.append(23)
shekf['foobar'] = thelist

в духе вашего комментария - что стилистически отчасти облом.

Однако, поскольку у вас есть проблемы с памятью, я определенно рекомендую , а не , используя эту сомнительную возможность обратной записи. Я думаю, что могу назвать это «сомнительным», так как я был тем, кто предложил и первым реализовал это, но это было много лет назад, и я в основном раскаялся в том, что сделал это - это порождает больше путаницы (как ваши доказательства Q), чем это допускает элегантность и удобство в перемещении кода, изначально написанного для работы с диктовками (который будет использовать первую идиому, а не вторую, и, следовательно, потребуется переписать для использования с полками без обратной трассировки). А, ну, извините, это показалось хорошей идеей в то время.

0 голосов
/ 04 февраля 2010

Использование модуля sqlite3, вероятно, ваш лучший выбор здесь. В любом случае, вы можете использовать sqlite полностью в памяти, поскольку его объем памяти может быть немного меньше, чем при использовании объектов python Как правило, это лучший выбор, чем использовать shelve; shelve использует pickle внизу, что редко бывает тем, что вы хотите.

Черт, вы можете просто преобразовать всю существующую базу данных в базу данных sqlite. sqlite хорош и быстр.

...