Содержание страницы
11.4. shelve – сохранение объектов Python¶shelve – Python object persistence
Исходный код: Lib/shelve.py
«Полка» (shelf) – это постоянный объект, похожий на словарь. Отличие от баз данных «dbm» в том, что значения (не ключи!) на полке могут быть практически произвольными объектами Python – всем, с чем может работать модуль pickle. Сюда входят большинство экземпляров классов, рекурсивные типы данных и объекты, содержащие много общих подобъектов. Ключи – обычные строки.
-
shelve.open(filename, flag='c', protocol=None, writeback=False)¶ Открывает постоянный словарь. Указанное имя файла является базовым для нижележащей базы данных. Как побочный эффект, к имени файла может быть добавлено расширение, и может быть создано более одного файла. По умолчанию нижележащий файл базы данных открывается для чтения и записи. Необязательный параметр flag имеет ту же интерпретацию, что и параметр flag функции
anydbm.open().По умолчанию для сериализации значений используются pickle версии 0. Версию протокола pickle можно указать с помощью параметра protocol.
Изменено в версии 2.3: Был добавлен параметр протокол.
Из-за семантики Python полка не может узнать, когда изменяется изменяемая запись постоянного словаря. По умолчанию изменённые объекты записываются только при присваивании полке (см. Пример). Если необязательный параметр writeback установлен в
True, все запрашиваемые записи также кэшируются в памяти и записываются обратно при вызовеsync()иclose(); это может упростить изменение изменяемых записей в постоянном словаре, но, если запрашивается много записей, может потреблять огромные объёмы памяти для кэша, а также может сделать операцию закрытия очень медленной, так как все запрошенные записи записываются обратно (нет способа определить, какие из запрошенных записей являются изменяемыми и какие из них были фактически изменены).Как и файловые объекты, объекты shelve следует явно закрывать, чтобы гарантировать сброс персистентных данных на диск.
Предупреждение
Поскольку модуль shelve основан на pickle, загружать полку из ненадёжного источника небезопасно. Как и в случае с pickle, загрузка полки может выполнить произвольный код.
Объекты Shelf поддерживают большинство методов, поддерживаемых словарями. Это упрощает переход от скриптов, основанных на словарях, к скриптам, требующим персистентного хранения.
Примечание: методы перехода на Python 3 (viewkeys(), viewvalues() и viewitems()) не поддерживаются.
Поддерживаются два дополнительных метода:
-
Shelf.sync()¶ Записывает обратно все записи из кэша, если полка была открыта с writeback, установленным в
True. Также очищает кэш и синхронизирует постоянный словарь на диске, если это возможно. Вызывается автоматически при закрытии полки с помощьюclose().
-
Shelf.close()¶ Синхронизирует и закрывает постоянный объект dict. Операции над закрытой полкой завершатся ошибкой
ValueError.
См. также
Рецепт постоянного словаря с широко поддерживаемыми форматами хранения и скоростью нативных словарей.
11.4.1. Ограничения¶Restrictions
Выбор используемого пакета базы данных (например,
dbm,gdbmилиbsddb) зависит от того, какой интерфейс доступен. Поэтому небезопасно открывать базу данных напрямую с помощьюdbm. База данных также (к сожалению) подвержена ограничениямdbm, если он используется – это означает, что представление объектов, хранящихся в базе данных, в pickle должно быть достаточно маленьким, и в редких случаях коллизии ключей могут привести к отказу базы данных в обновлениях.Модуль
shelveне поддерживает одновременный доступ на чтение и запись к объектам на полке. (Одновременный доступ на чтение от нескольких программ безопасен.) Когда программа открыла полку для записи, никакая другая программа не должна открывать её для чтения или записи. Для решения этой проблемы можно использовать блокировку файлов в Unix, но она отличается в разных версиях Unix и требует знания используемой реализации базы данных.
-
class
shelve.Shelf(dict, protocol=None, writeback=False)¶ Подкласс
UserDict.DictMixin, который хранит значения, сериализованные в pickle, в объекте dict.По умолчанию для сериализации значений используются pickle версии 0. Версию протокола pickle можно указать с помощью параметра protocol. См. документацию
pickleдля обсуждения протоколов pickle.Изменено в версии 2.3: Был добавлен параметр протокол.
Если параметр writeback равен
True, объект будет хранить кэш всех запрошенных записей и записывать их обратно в dict при синхронизации и закрытии. Это позволяет естественно работать с изменяемыми записями, но может потреблять значительно больше памяти и замедлять синхронизацию и закрытие.
-
class
shelve.BsdDbShelf(dict, protocol=None, writeback=False)¶ Подкласс
Shelf, который предоставляетfirst(),next(),previous(),last()иset_location(), доступные в модулеbsddb, но отсутствующие в других модулях баз данных. Объект dict, передаваемый конструктору, должен поддерживать эти методы. Обычно это достигается вызовом одной из функцийbsddb.hashopen(),bsddb.btopen()илиbsddb.rnopen(). Необязательные параметры protocol и writeback имеют ту же интерпретацию, что и для классаShelf.
-
class
shelve.DbfilenameShelf(filename, flag='c', protocol=None, writeback=False)¶ Подкласс
Shelf, который принимает filename вместо объекта, похожего на словарь. Базовый файл будет открыт с помощьюanydbm.open(). По умолчанию файл создаётся и открывается для чтения и записи. Необязательный параметр flag имеет то же значение, что и для функцииopen(). Необязательные параметры протокол и writeback имеют то же значение, что и для классаShelf.
11.4.2. Пример¶Example
Обобщая интерфейс (key – строка, data – произвольный объект):
import shelve
d = shelve.open(filename) # open -- файл может получить суффикс, добавленный низкоуровневой
# библиотекой
d[key] = data # сохраняет данные по ключу (перезаписывает старые данные, если
# используется существующий ключ)
data = d[key] # извлечь копию данных по ключу (вызывает KeyError, если такого ключа нет)
# такого ключа)
del d[key] # удалить данные, хранящиеся по ключу (вызывает KeyError
# если такого ключа нет)
flag = d.has_key(key) # true, если ключ существует
klist = d.keys() # список всех существующих ключей (медленно!)
# так как d был открыт БЕЗ writeback=True, внимание:
d['xx'] = range(4) # это работает как ожидается, но...
d['xx'].append(5) # *это не так!* -- d['xx'] по-прежнему range(4)!
# открыв d без writeback=True, нужно писать код аккуратно:
temp = d['xx'] # извлекает копию
temp.append(5) # изменяет копию
d['xx'] = temp # сохраняет изменённую копию обратно для сохранения
# или, d=shelve.open(filename,writeback=True) позволил бы просто написать
# d['xx'].append(5) и это бы работало как ожидается, НО это также бы
# потребляло больше памяти и замедляло операцию d.close().
d.close() # закрыть его
См. также
- Модуль
anydbm Общий интерфейс для баз данных стиля
dbm.- Модуль
bsddb Интерфейс базы данных
dbBSD.- Модуль
dbhash Тонкая обёртка вокруг
bsddb, которая предоставляет функциюopen(), подобно другим модулям баз данных.- Модуль
dbm Стандартный интерфейс базы данных Unix.
- Модуль
dumbdbm Переносимая реализация интерфейса
dbm.- Модуль
gdbm Интерфейс базы данных GNU, основанный на интерфейсе
dbm.- Модуль
pickle Сериализация объектов, используемая
shelve.- Модуль
cPickle Высокопроизводительная версия
pickle.