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

shelve.md

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

1> **Источник:** https://python-all.ru/3.1/library/shelve.html2>3> «Документация Python на русском» – неофициальный перевод официальной документации Python: версии от 2.6 до 3.16, полнотекстовый поиск, английский оригинал рядом с переводом. Эта Markdown-версия страницы предназначена для работы с LLM: вставьте её в ChatGPT, Claude или Cursor.45---67# 11.3. `shelve` – сохранение объектов Python89«Полка» (shelf) – это постоянный объект, похожий на словарь. Отличие от баз данных «dbm» в том, что значения (не ключи!) в полке могут быть практически произвольными объектами Python – всем, что поддерживает модуль [`pickle`](https://python-all.ru/3.1/library/pickle.html#module-pickle). Сюда входят большинство экземпляров классов, рекурсивные типы данных и объекты, содержащие множество общих подобъектов. Ключи – обычные строки.1011#### `shelve.open(filename[, flag='c'[, protocol=None[, writeback=False]]])`1213Открывает постоянный словарь. Указанное имя файла является базовым именем для базового файла базы данных. Как побочный эффект, к имени файла может быть добавлено расширение и может быть создано более одного файла. По умолчанию базовый файл базы данных открывается для чтения и записи. Необязательный параметр *flag* имеет ту же интерпретацию, что и параметр *flag* в функции [`dbm.open()`](https://python-all.ru/3.1/library/dbm.html#dbm.open).1415По умолчанию для сериализации значений используются pickle версии 3. Версию протокола pickle можно указать с помощью параметра *протокол*.1617Из-за семантики Python полка не может узнать, когда изменяется изменяемая запись постоянного словаря. По умолчанию изменённые объекты записываются *только* при присваивании полке (см. [*Пример*](https://python-all.ru/3.1/library/shelve.html#shelve-example)). Если необязательный параметр *writeback* установлен в *True*, все accessed записи также кэшируются в памяти и записываются обратно при вызове [`sync()`](https://python-all.ru/3.1/library/shelve.html#shelve.Shelf.sync) и [`close()`](https://python-all.ru/3.1/library/shelve.html#shelve.Shelf.close); это может упростить изменение изменяемых записей в постоянном словаре, но, если получено много записей, может потреблять огромные объёмы памяти для кэша и сделать операцию закрытия очень медленной, так как все полученные записи записываются обратно (нет способа определить, какие из полученных записей являются изменяемыми, и какие из них были фактически изменены).1819> **Примечание**20>21> Не полагайтесь на то, что shelf будет закрыт автоматически; всегда явно вызывайте `close()`, когда он больше не нужен, или используйте оператор [`with`](https://python-all.ru/3.1/reference/compound_stmts.html#with) с [`contextlib.closing()`](https://python-all.ru/3.1/library/contextlib.html#contextlib.closing).2223> **Предупреждение**24>25> Поскольку модуль `shelve` основан на [`pickle`](https://python-all.ru/3.1/library/pickle.html#module-pickle), загружать хранилище из ненадёжного источника небезопасно. Как и в случае с pickle, загрузка хранилища может выполнить произвольный код.2627Объекты Shelf поддерживают все методы, поддерживаемые словарями. Это облегчает переход от скриптов, основанных на словарях, к скриптам, требующим постоянного хранения.2829Поддерживаются два дополнительных метода:3031#### `Shelf.sync()`3233Записывает обратно все записи в кэше, если полка была открыта с3435*writeback*3637установленным в3839[`True`](https://python-all.ru/3.1/library/constants.html#True)4041. Также очищает кэш и синхронизирует постоянный словарь на диске, если это возможно. Это вызывается автоматически, когда полка закрывается с помощью4243[`close()`](https://python-all.ru/3.1/library/shelve.html#shelve.Shelf.close)4445.4647#### `Shelf.close()`4849Синхронизирует и закрывает постоянный объект5051*dict*5253. Операции над закрытой полкой будут завершаться с5455[`ValueError`](https://python-all.ru/3.1/library/exceptions.html#ValueError)5657.5859> **См. также**60>61> [Рецепт постоянного словаря](https://python-all.ru/3.1/library/shelve.html) с широко поддерживаемыми форматами хранения и скоростью нативных словарей.6263## 11.3.1. Ограничения6465>6667- Выбор того, какой пакет базы данных будет использоваться (например, [`dbm.ndbm`](https://python-all.ru/3.1/library/dbm.html#module-dbm.ndbm) или [`dbm.gnu`](https://python-all.ru/3.1/library/dbm.html#module-dbm.gnu)), зависит от того, какой интерфейс доступен. Поэтому небезопасно открывать базу данных напрямую с помощью [`dbm`](https://python-all.ru/3.1/library/dbm.html#module-dbm). Кроме того, база данных, к сожалению, подвержена ограничениям [`dbm`](https://python-all.ru/3.1/library/dbm.html#module-dbm), если она используется – это означает, что (сериализованное (pickle) представление) объектов, хранящихся в базе данных, должно быть достаточно маленьким, и в редких случаях коллизии ключей могут привести к тому, что база данных откажется обновляться.68- Модуль `shelve` не поддерживает *параллельный* доступ на чтение и запись к сохранённым объектам. (Одновременный доступ нескольких программ только на чтение безопасен.) Когда программа открыла хранилище для записи, никакая другая программа не должна открывать его для чтения или записи. Для решения этой проблемы можно использовать файловую блокировку Unix, но она различается в разных версиях Unix и требует знания используемой реализации базы данных.6970#### `class shelve.Shelf(dict[, protocol=None[, writeback=False]])`7172Подкласс [`collections.MutableMapping`](https://python-all.ru/3.1/library/collections.html#collections.MutableMapping), который хранит сериализованные значения в объекте *dict*.7374По умолчанию для сериализации значений используется версия 0 pickle. Версию протокола pickle можно указать через параметр *protocol*. См. документацию [`pickle`](https://python-all.ru/3.1/library/pickle.html#module-pickle) для обсуждения протоколов pickle.7576Если параметр *writeback* равен `True`, объект будет хранить кэш всех полученных записей и записывать их обратно в *dict* при синхронизации и закрытии. Это позволяет естественным образом работать с изменяемыми записями, но может потреблять гораздо больше памяти и замедлить синхронизацию и закрытие.7778#### `class shelve.BsdDbShelf(dict[, protocol=None[, writeback=False]])`7980Подкласс8182[`Shelf`](https://python-all.ru/3.1/library/shelve.html#shelve.Shelf)8384, предоставляющий методы8586`first()`8788,8990`next()`9192,9394`previous()`9596,9798`last()`99100и101102`set_location()`103104, которые доступны в стороннем модуле105106`bsddb`107108от109110[pybsddb](https://python-all.ru/3.1/library/shelve.html)111112, но отсутствуют в других модулях баз данных. Объект113114*dict*115116, передаваемый конструктору, должен поддерживать эти методы. Обычно это достигается вызовом одной из функций117118`bsddb.hashopen()`119120,121122`bsddb.btopen()`123124или125126`bsddb.rnopen()`127128. Необязательные параметры129130*протокол*131132и133134*writeback*135136имеют тот же смысл, что и для класса137138[`Shelf`](https://python-all.ru/3.1/library/shelve.html#shelve.Shelf)139140.141142#### `class shelve.DbfilenameShelf(filename[, flag='c'[, protocol=None[, writeback=False]]])`143144Подкласс145146[`Shelf`](https://python-all.ru/3.1/library/shelve.html#shelve.Shelf)147148, который принимает имя файла149150*filename*151152вместо объекта, похожего на словарь. Базовый файл будет открыт с помощью153154[`dbm.open()`](https://python-all.ru/3.1/library/dbm.html#dbm.open)155156. По умолчанию файл будет создан и открыт для чтения и записи. Необязательный параметр157158*flag*159160имеет ту же интерпретацию, что и для функции161162[`open()`](https://python-all.ru/3.1/library/shelve.html#shelve.open)163164. Необязательные параметры165166*protocol*167168и169170*writeback*171172имеют ту же интерпретацию, что и для класса173174[`Shelf`](https://python-all.ru/3.1/library/shelve.html#shelve.Shelf)175176.177178## 11.3.2. Пример179180Обобщая интерфейс (`key` – строка, `data` – произвольный объект):181182```python183import shelve184185d = shelve.open(filename) # open -- файл может получить суффикс, добавленный низкоуровневой186                          # библиотекой187188d[key] = data   # сохраняет данные по ключу (перезаписывает старые данные, если189                # используется существующий ключ)190data = d[key]   # извлечь копию данных по ключу (вызывает KeyError, если такого ключа нет)191                # такого ключа)192del d[key]      # удалить данные, хранящиеся по ключу (вызывает KeyError193                # если такого ключа нет)194flag = key in d        # true, если ключ существует195klist = list(d.keys()) # список всех существующих ключей (медленно!)196197# так как d был открыт БЕЗ writeback=True, внимание:198d['xx'] = [0, 1, 2]    # это работает как ожидается, но...199d['xx'].append(3)      # *это не работает!* -- d['xx'] всё ещё [0, 1, 2]!200201# открыв d без writeback=True, нужно писать код аккуратно:202temp = d['xx']      # извлекает копию203temp.append(5)      # изменяет копию204d['xx'] = temp      # сохраняет изменённую копию обратно для сохранения205206# или, d=shelve.open(filename,writeback=True) позволил бы просто написать207# d['xx'].append(5) и это бы работало как ожидается, НО это также бы208# потребляло больше памяти и замедляло операцию d.close().209210d.close()       # закрыть его211```212213> **См. также**214>215> **Модуль [`dbm`](https://python-all.ru/3.1/library/dbm.html#module-dbm)**216>217> Общий интерфейс для баз данных типа218>219> `dbm`220>221> .222>223> **Модуль [`pickle`](https://python-all.ru/3.1/library/pickle.html#module-pickle)**224>225> Сериализация объектов, используемая модулем226>227> `shelve`228>229> .230