Документация Python неофициальный перевод

shelve.md

168 строк · 19.8 КБ · обычная страница · сырой текст · скачать

1> **Источник:** https://python-all.ru/3.15/library/shelve.html2>3> «Документация Python на русском» – неофициальный перевод официальной документации Python: версии от 2.6 до 3.16, полнотекстовый поиск, английский оригинал рядом с переводом. Эта Markdown-версия страницы предназначена для работы с LLM: вставьте её в ChatGPT, Claude или Cursor.45---67# `shelve` – сохранение объектов Python89**Исходный код:** [Lib/shelve.py](https://python-all.ru/src/3.15/Lib/shelve.py)1011---1213«Полка» (shelf) – это постоянный объект, похожий на словарь. Отличие от баз данных «dbm» в том, что значения (не ключи!) на полке могут быть практически произвольными объектами Python – всем, с чем может работать модуль [`pickle`](https://python-all.ru/3.15/library/pickle.html#module-pickle). Сюда входят большинство экземпляров классов, рекурсивные типы данных и объекты, содержащие много общих подобъектов. Ключи – обычные строки.1415#### `shelve.open(filename, flag='c', protocol=None, writeback=False, *, serializer=None, deserializer=None)`1617Открывает постоянный словарь. Указанное имя файла является базовым для нижележащей базы данных. Как побочный эффект, к имени файла может быть добавлено расширение, и может быть создано более одного файла. По умолчанию нижележащий файл базы данных открывается для чтения и записи. Необязательный параметр *flag* имеет ту же интерпретацию, что и параметр *flag* функции [`dbm.open()`](https://python-all.ru/3.15/library/dbm.html#dbm.open).1819По умолчанию для сериализации значений используются рассолы (pickles), созданные с помощью [`pickle.DEFAULT_PROTOCOL`](https://python-all.ru/3.15/library/pickle.html#pickle.DEFAULT_PROTOCOL). Версию протокола pickle можно указать с помощью параметра *protocol*.2021Из-за семантики Python полка не может узнать, когда изменяется изменяемая запись постоянного словаря. По умолчанию изменённые объекты записываются *только* при присваивании полке (см. [Пример](https://python-all.ru/3.15/library/shelve.html#shelve-example)). Если необязательный параметр *writeback* установлен в `True`, все запрашиваемые записи также кэшируются в памяти и записываются обратно при вызове [`sync()`](https://python-all.ru/3.15/library/shelve.html#shelve.Shelf.sync) и [`close()`](https://python-all.ru/3.15/library/shelve.html#shelve.Shelf.close); это может упростить изменение изменяемых записей в постоянном словаре, но, если запрашивается много записей, может потреблять огромные объёмы памяти для кэша, а также может сделать операцию закрытия очень медленной, так как все запрошенные записи записываются обратно (нет способа определить, какие из запрошенных записей являются изменяемыми и какие из них были фактически изменены).2223По умолчанию `shelve` использует [`pickle.dumps()`](https://python-all.ru/3.15/library/pickle.html#pickle.dumps) и [`pickle.loads()`](https://python-all.ru/3.15/library/pickle.html#pickle.loads) для сериализации и десериализации. Это можно изменить, передав соответственно *serializer* и *deserializer*.2425Аргумент *serializer* должен быть вызываемым объектом, который принимает объект `obj` и *протокол* в качестве входных данных и возвращает представление `obj` в виде [байтоподобного объекта](https://python-all.ru/3.15/glossary.html#term-bytes-like-object); значение *протокол* может игнорироваться сериализатором.2627Аргумент *deserializer* должен быть вызываемым объектом, который принимает сериализованный объект, представленный в виде объекта [`bytes`](https://python-all.ru/3.15/library/stdtypes.html#bytes), и возвращает соответствующий объект.2829Исключение [`ShelveError`](https://python-all.ru/3.15/library/shelve.html#shelve.ShelveError) возбуждается, если указан *serializer*, но не указан *deserializer*, или наоборот.3031Изменено в версии 3.10: [`pickle.DEFAULT_PROTOCOL`](https://python-all.ru/3.15/library/pickle.html#pickle.DEFAULT_PROTOCOL) теперь используется как протокол pickle по умолчанию.3233Изменено в версии 3.11: Принимает [объект, подобный пути](https://python-all.ru/3.15/glossary.html#term-path-like-object) для имени файла.3435Изменено в версии 3.15: Принимает пользовательские функции *serializer* и *deserializer* вместо [`pickle.dumps()`](https://python-all.ru/3.15/library/pickle.html#pickle.dumps) и [`pickle.loads()`](https://python-all.ru/3.15/library/pickle.html#pickle.loads).3637> **Примечание**38>39> Не полагайтесь на автоматическое закрытие полки; всегда явно вызывайте [`close()`](https://python-all.ru/3.15/library/shelve.html#shelve.Shelf.close), когда она больше не нужна, или используйте `shelve.open()` как менеджер контекста:40>41> ```python42> with shelve.open('spam') as db:43>     db['eggs'] = 'eggs'44> ```4546> **Предупреждение**47>48> Поскольку модуль `shelve` основан на [`pickle`](https://python-all.ru/3.15/library/pickle.html#module-pickle), загружать полку из ненадёжного источника небезопасно. Как и в случае с pickle, загрузка полки может выполнить произвольный код.4950Объекты Shelf поддерживают большинство методов и операций словарей (за исключением копирования, конструкторов и операторов `|` и `|=`). Это упрощает переход от скриптов на основе словарей к скриптам, требующим постоянного хранения.5152Поддерживаются два дополнительных метода:5354#### `Shelf.sync()`5556Записывает обратно все записи в кеше, если полка была открыта с *writeback*, установленным в [`True`](https://python-all.ru/3.15/library/constants.html#True). Также очищает кеш и синхронизирует постоянный словарь на диске, если это возможно. Это вызывается автоматически при вызове [`reorganize()`](https://python-all.ru/3.15/library/shelve.html#shelve.Shelf.reorganize) или закрытии полки с помощью [`close()`](https://python-all.ru/3.15/library/shelve.html#shelve.Shelf.close).5758#### `Shelf.reorganize()`5960Вызывает [`sync()`](https://python-all.ru/3.15/library/shelve.html#shelve.Shelf.sync) и пытается уменьшить занимаемое на диске пространство, удаляя пустое пространство, образовавшееся в результате удалений.6162Добавлено в версии 3.15.6364#### `Shelf.close()`6566Синхронизирует и закрывает постоянный объект *dict*. Операции над закрытой полкой завершатся ошибкой [`ValueError`](https://python-all.ru/3.15/library/exceptions.html#ValueError).6768> **См. также**69>70> [Рецепт постоянного словаря](https://python-all.ru/3.15/library/shelve.html) с широко поддерживаемыми форматами хранения и скоростью нативных словарей.7172## Ограничения7374- Выбор используемого пакета базы данных (например, [`dbm.ndbm`](https://python-all.ru/3.15/library/dbm.html#module-dbm.ndbm) или [`dbm.gnu`](https://python-all.ru/3.15/library/dbm.html#module-dbm.gnu)) зависит от доступного интерфейса. Поэтому открывать базу данных напрямую с помощью [`dbm`](https://python-all.ru/3.15/library/dbm.html#module-dbm) небезопасно. База данных также (к сожалению) подвержена ограничениям `dbm`, если он используется – это означает, что (рассоленное представление) хранящихся в базе объектов должно быть достаточно небольшим, и в редких случаях коллизии ключей могут привести к отказу базы данных в обновлении.75- Модуль `shelve` не поддерживает *одновременный* доступ на чтение и запись к объектам на полке. (Одновременный доступ на чтение от нескольких программ безопасен.) Когда программа открыла полку для записи, никакая другая программа не должна открывать её для чтения или записи. Для решения этой проблемы можно использовать блокировку файлов в Unix, но она отличается в разных версиях Unix и требует знания используемой реализации базы данных.76- В macOS [`dbm.ndbm`](https://python-all.ru/3.15/library/dbm.html#module-dbm.ndbm) может незаметно повредить файл базы данных при обновлениях, что может привести к серьёзным сбоям при попытке чтения из базы данных.77- [`Shelf.reorganize()`](https://python-all.ru/3.15/library/shelve.html#shelve.Shelf.reorganize) может быть недоступен для всех пакетов баз данных и может временно увеличивать использование ресурсов (особенно дискового пространства) при вызове. Кроме того, он никогда не запускается автоматически и вместо этого должен вызываться явно.7879#### `class shelve.Shelf(dict, protocol=None, writeback=False, keyencoding='utf-8', *, serializer=None, deserializer=None)`8081Подкласс [`collections.abc.MutableMapping`](https://python-all.ru/3.15/library/collections.abc.html#collections.abc.MutableMapping), который хранит рассоленные значения в объекте *dict*.8283По умолчанию для сериализации значений используются рассолы (pickles), созданные с помощью [`pickle.DEFAULT_PROTOCOL`](https://python-all.ru/3.15/library/pickle.html#pickle.DEFAULT_PROTOCOL). Версию протокола pickle можно указать с помощью параметра *protocol*. См. документацию [`pickle`](https://python-all.ru/3.15/library/pickle.html#module-pickle) для обсуждения протоколов pickle.8485Если параметр *writeback* равен `True`, объект будет хранить кэш всех запрошенных записей и записывать их обратно в *dict* при синхронизации и закрытии. Это позволяет естественно работать с изменяемыми записями, но может потреблять значительно больше памяти и замедлять синхронизацию и закрытие.8687Параметр *keyencoding* – это кодировка, используемая для кодирования ключей перед их использованием в нижележащем словаре.8889Параметры *serializer* и *deserializer* имеют ту же интерпретацию, что и в [`open()`](https://python-all.ru/3.15/library/shelve.html#shelve.open).9091Объект `Shelf` также можно использовать как менеджер контекста; в этом случае он будет автоматически закрыт при завершении блока [`with`](https://python-all.ru/3.15/reference/compound_stmts.html#with).9293Изменено в версии 3.2: Добавлен параметр *keyencoding*; ранее ключи всегда кодировались в UTF-8.9495Изменено в версии 3.4: Добавлена поддержка менеджера контекста.9697Изменено в версии 3.10: [`pickle.DEFAULT_PROTOCOL`](https://python-all.ru/3.15/library/pickle.html#pickle.DEFAULT_PROTOCOL) теперь используется как протокол pickle по умолчанию.9899Изменено в версии 3.15: Добавлены параметры *serializer* и *deserializer*.100101#### `class shelve.BsdDbShelf(dict, protocol=None, writeback=False, keyencoding='utf-8', *, serializer=None, deserializer=None)`102103Подкласс [`Shelf`](https://python-all.ru/3.15/library/shelve.html#shelve.Shelf), который предоставляет методы `first()`, `next()`, `previous()`, `last()` и `set_location()`. Они доступны в стороннем модуле `bsddb` из [pybsddb](https://python-all.ru/3.15/library/shelve.html), но не в других модулях баз данных. Объект *dict*, передаваемый конструктору, должен поддерживать эти методы. Обычно это достигается вызовом одной из функций `bsddb.hashopen()`, `bsddb.btopen()` или `bsddb.rnopen()`. Необязательные параметры *протокол*, *writeback*, *keyencoding*, *serializer* и *deserializer* имеют ту же интерпретацию, что и в [`open()`](https://python-all.ru/3.15/library/shelve.html#shelve.open).104105Изменено в версии 3.15: Добавлены параметры *serializer* и *deserializer*.106107#### `class shelve.DbfilenameShelf(filename, flag='c', protocol=None, writeback=False, *, serializer=None, deserializer=None)`108109Подкласс [`Shelf`](https://python-all.ru/3.15/library/shelve.html#shelve.Shelf), который принимает *filename* вместо dict-подобного объекта. Основной файл будет открыт с помощью [`dbm.open()`](https://python-all.ru/3.15/library/dbm.html#dbm.open). По умолчанию файл будет создан и открыт для чтения и записи. Необязательный параметр *flag* имеет ту же интерпретацию, что и для функции [`open()`](https://python-all.ru/3.15/library/shelve.html#shelve.open). Необязательные параметры *протокол*, *writeback*, *serializer* и *deserializer* имеют ту же интерпретацию, что и в [`open()`](https://python-all.ru/3.15/library/shelve.html#shelve.open).110111Изменено в версии 3.15: Добавлены параметры *serializer* и *deserializer*.112113## Пример114115Обобщая интерфейс (`key` – строка, `data` – произвольный объект):116117```python118import shelve119120d = shelve.open(filename)  # open -- файл может получить суффикс, добавленный низкоуровневой121                           # библиотекой122123d[key] = data              # сохраняет данные по ключу (перезаписывает старые данные, если124                           # используется существующий ключ)125data = d[key]              # извлекает КОПИЮ данных по ключу (вызывает KeyError126                           # если такого ключа нет)127del d[key]                 # удалить данные, хранящиеся по ключу (вызывает KeyError128                           # если такого ключа нет)129130flag = key in d            # true, если ключ существует131klist = list(d.keys())     # список всех существующих ключей (медленно!)132133# так как d был открыт БЕЗ writeback=True, внимание:134d['xx'] = [0, 1, 2]        # это работает как ожидается, но...135d['xx'].append(3)          # *это не работает!* -- d['xx'] всё ещё [0, 1, 2]!136137# открыв d без writeback=True, нужно писать код аккуратно:138temp = d['xx']             # извлекает копию139temp.append(5)             # изменяет копию140d['xx'] = temp             # сохраняет изменённую копию обратно для сохранения141142# или, d=shelve.open(filename,writeback=True) позволил бы просто написать143# d['xx'].append(5) и это бы работало как ожидается, НО это также бы144# потребляло больше памяти и замедляло операцию d.close().145146d.close()                  # закрыть его147```148149## Исключения150151#### `exception shelve.ShelveError`152153Исключение возбуждается, когда один из аргументов *deserializer* и *serializer* отсутствует в [`open()`](https://python-all.ru/3.15/library/shelve.html#shelve.open), [`Shelf`](https://python-all.ru/3.15/library/shelve.html#shelve.Shelf), [`BsdDbShelf`](https://python-all.ru/3.15/library/shelve.html#shelve.BsdDbShelf) и [`DbfilenameShelf`](https://python-all.ru/3.15/library/shelve.html#shelve.DbfilenameShelf).154155Аргументы *deserializer* и *serializer* должны передаваться вместе.156157Добавлено в версии 3.15.158159> **См. также**160>161> **Модуль [`dbm`](https://python-all.ru/3.15/library/dbm.html#module-dbm)**162>163> Общий интерфейс для баз данных стиля `dbm`.164>165> **Модуль [`pickle`](https://python-all.ru/3.15/library/pickle.html#module-pickle)**166>167> Сериализация объектов, используемая `shelve`.168