shelve — Постоянное хранение объектов Python
Исходный код: Lib/shelve.py
«Шелф» — это персистентный, подобный словарю объект. Отличие от баз данных «dbm» заключается в том, что значения (а не ключи!) в шельфе могут быть произвольными объектами Python — всё, что может обработать модуль pickle. Это включает в себя большинство экземпляров классов, рекурсивные типы данных и объекты, содержащие множество общих подобъектов. Ключи являются обычными строками.
-
shelve.open(filename, flag='c', protocol=None, writeback=False) -
Открыть персистентный словарь. Указанное имя файла — это базовое имя файла для основной базы данных. В качестве побочного эффекта, к имени файла может быть добавлено расширение, и может быть создано более одного файла. По умолчанию, базовый файл базы данных открывается для чтения и записи. Необязательный параметр flag имеет то же значение, что и параметр flag функции
dbm.open().По умолчанию используются объекты pickle версии 3 для сериализации значений. Версия протокола pickle может быть указана с помощью параметра protocol.
Из-за семантики Python, шельф не может знать, когда изменяется мутабельный элемент персистентного словаря. По умолчанию изменённые объекты записываются только при присвоении их шельфу (см. Пример). Если необязательный параметр writeback установлен в
True, все обращённые элементы также кешируются в памяти и записываются обратно при вызовеsync()иclose(); это может сделать удобнее изменение мутабельных элементов в персистентном словаре, но, если многие элементы обращаются, это может потребовать больших объёмов памяти для кэша, и операция закрытия может занять много времени, так как все обращённые элементы записываются обратно (нет способа определить, какие элементы обращаются, мутабельны, или какие из них на самом деле были изменены).Примечание
Не полагайтесь на автоматическое закрытие шельфа; всегда явно вызывайте
close(), когда он больше не нужен, или используйтеshelve.open()как менеджер контекста:with shelve.open('spam') as db: db['eggs'] = 'eggs'
Предупреждение
Так как модуль shelve основан на модуле pickle, загрузка шельфа из ненадежного источника небезопасна. Как и при работе с pickle, загрузка шельфа может выполнить произвольный код.
Объекты шельфа поддерживают все методы, поддерживаемые словарями. Это облегчает переход от сценариев, основанных на словарях, к сценариям, требующим постоянного хранения.
Поддерживаются две дополнительные функции:
-
Shelf.sync() -
Записать обратно все элементы в кэше, если шельф был открыт с параметром writeback, установленным в
True. Также очистить кэш и синхронизировать персистентный словарь на диске, если это возможно. Это вызывается автоматически при закрытии шельфа с помощьюclose().
-
Shelf.close() -
Синхронизировать и закрыть персистентный объект dict. Операции с закрытым шельфом завершатся ошибкой
ValueError.
См. также
Рецепт персистентного словаря с широко поддерживаемыми форматами хранения и скоростью, сопоставимой с обычными словарями.
Ограничения
- Выбор пакета базы данных (например,
dbm.ndbmилиdbm.gnu) зависит от доступного интерфейса. Поэтому небезопасно открывать базу данных напрямую с помощьюdbm. База данных также (к сожалению) ограничена ограничениямиdbm, если она используется — это означает, что (сериализованное представление) хранимых в базе данных объектов должно быть достаточно маленьким, и в редких случаях столкновения ключей могут привести к отказу базы данных в обновлении. - Модуль
shelveне поддерживает конкурентный доступ для чтения/записи к объектам шельфа. (Множественный одновременный доступ для чтения безопасен.) Когда программа имеет открытый для записи шельф, ни одна другая программа не должна иметь его открытым для чтения или записи. Блокировка файлов Unix может использоваться для решения этой проблемы, но это отличается в разных версиях Unix и требует знаний об используемой реализации базы данных.
-
class shelve.Shelf(dict, protocol=None, writeback=False, keyencoding='utf-8') -
Подкласс
collections.abc.MutableMapping, хранящий сериализованные значения в объекте dict.По умолчанию используются объекты pickle версии 3 для сериализации значений. Версия протокола pickle может быть указана с помощью параметра protocol. См. документацию по
pickleдля обсуждения протоколов pickle.Если параметр writeback равен
True, объект будет содержать кэш всех обращённых элементов и запишет их обратно в dict в момент синхронизации и закрытия. Это позволяет естественным образом работать с мутабельными элементами, но может потреблять гораздо больше памяти и сильно замедлять синхронизацию и закрытие.Параметр keyencoding — кодировка, используемая для кодирования ключей перед их использованием с основным словарем.
Объект
Shelfтакже может использоваться как менеджер контекста, в этом случае он будет автоматически закрыт при завершении блокаwith.Изменено в версии 3.2: Добавлен параметр keyencoding; ранее ключи всегда кодировались в UTF-8.
Изменено в версии 3.4: Добавлена поддержка менеджеров контекста.
-
class shelve.BsdDbShelf(dict, protocol=None, writeback=False, keyencoding='utf-8') -
Подкласс
Shelf, который предоставляетfirst(),next(),previous(),last()иset_location(), которые доступны в стороннем модулеbsddbиз pybsddb, но не в других модулях базы данных. Объект dict, переданный в конструктор, должен поддерживать эти методы. Это обычно достигается вызовом одного изbsddb.hashopen(),bsddb.btopen()илиbsddb.rnopen(). Необязательные параметры protocol, writeback и keyencoding имеют то же значение, что и для классаShelf.
-
class shelve.DbfilenameShelf(filename, flag='c', protocol=None, writeback=False) -
Подкласс
Shelf, который принимает filename вместо объекта типа dict. Базовый файл будет открыт с помощьюdbm.open(). По умолчанию файл будет создан и открыт для чтения и записи. Необязательный параметр flag имеет то же значение, что и для функцииopen(). Необязательные параметры protocol и writeback имеют то же значение, что и для классаShelf.
Пример
Для подведения итогов интерфейса (key — строка, data — произвольный объект):
import shelve
d = shelve.open(filename) # open -- file may get suffix added by low-level
# library
d[key] = data # store data at key (overwrites old data if
# using an existing key)
data = d[key] # retrieve a COPY of data at key (raise KeyError
# if no such key)
del d[key] # delete data stored at key (raises KeyError
# if no such key)
flag = key in d # true if the key exists
klist = list(d.keys()) # a list of all existing keys (slow!)
# as d was opened WITHOUT writeback=True, beware:
d['xx'] = [0, 1, 2] # this works as expected, but...
d['xx'].append(3) # *this doesn't!* -- d['xx'] is STILL [0, 1, 2]!
# having opened d without writeback=True, you need to code carefully:
temp = d['xx'] # extracts the copy
temp.append(5) # mutates the copy
d['xx'] = temp # stores the copy right back, to persist it
# or, d=shelve.open(filename,writeback=True) would let you just code
# d['xx'].append(5) and have it work as expected, BUT it would also
# consume more memory and make the d.close() operation slower.
d.close() # close it
© 2001–2022 Python Software Foundation
Licensed under the PSF License.
https://docs.python.org/3.8/library/shelve.html