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 поддерживают все методы, поддерживаемые словарями. Это упрощает переход от сценариев, основанных на словарях, к тем, которые требуют персистентного хранения.
Поддерживаются два дополнительных метода:
-
Shelf.sync() -
Перезаписывает все записи в кэше, если шелф был открыт с параметром writeback, установленным в
True. Также очищает кэш и синхронизирует персистентный словарь на диске, если это возможно. Это вызывается автоматически при закрытии шелфа с помощьюclose().
-
Shelf.close() -
Синхронизирует и закрывает персистентный объект dict. Операции с закрытым шелфом завершатся ошибкой
ValueError.
См. также
Рецепт персистентного словаря с широко поддерживаемыми форматами хранения и скоростью, сопоставимой со скоростью встроенных словарей.
12.3.1. Ограничения
- Выбор пакета баз данных (например,
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.
12.3.2. Пример
Для резюме интерфейса (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–2020 Python Software Foundation
Licensed under the PSF License.
https://docs.python.org/3.6/library/shelve.html