shelve — Постоянство объекта Python

Исходный код: Lib/shelve.py


«shelf» - это постоянный объект, подобный словарю. Разница с базами данных «dbm» заключается в том, что значения (а не ключи!) в shelf могут быть, по сути, произвольными объектами Python - всем, что может обрабатывать модуль pickle. Это включает в себя большинство экземпляров классов, рекурсивные типы данных и объекты, содержащие множество общих подобъектов. Ключи - это обычные строки.

shelve.open(filename, flag='c', protocol=None, writeback=False)

Откройте постоянный словарь. Указанное имя файла является базовым для базовой базы данных. В качестве побочного эффекта к имени файла может быть добавлено расширение и может быть создано более одного файла. По умолчанию базовый файл базы данных открыт для чтения и записи. Необязательный параметр flag имеет ту же интерпретацию, что и параметр flag для dbm.open().

По умолчанию для сериализации значений используются рассолы, созданные с помощью pickle.DEFAULT_PROTOCOL. Версию протокола рассола можно указать с помощью параметра protocol.

Из-за семантики Python полка не может знать, когда изменяется изменяемая запись в постоянном словаре. По умолчанию измененные объекты записываются только при назначении на полку (см. Пример). Если для необязательного параметра обратная запись задано значение True, все записи, к которым осуществляется доступ, также кэшируются в памяти и записываются обратно в sync() и close(); это может упростить изменение изменяемых записей в постоянном словаре, но при обращении ко многим записям это может занять огромные объемы памяти для кэша и может сильно замедлить операцию закрытия, поскольку все записи, к которым осуществляется доступ, записываются обратно (нет способа определить, к каким записям осуществляется доступ). изменчивы, ни какие из них на самом деле были изменены).

Изменено в версии 3.10: pickle.DEFAULT_PROTOCOL теперь используется в качестве протокола pickle по умолчанию.

Изменено в версии 3.11: Принимает path-like object в качестве имени файла.

Примечание

Не полагайтесь на то, что полка закроется автоматически; всегда вызывайте close() явно, когда она вам больше не нужна, или используйте shelve.open() в качестве контекстного менеджера:

with shelve.open('spam') as db:
    db['eggs'] = 'eggs'

Предупреждение

Поскольку модуль shelve поддерживается pickle, загрузка полки из ненадежного источника небезопасна. Как и в случае с pickle, при загрузке полки может выполняться произвольный код.

Объекты Shelf поддерживают большинство методов и операций, поддерживаемых словарями (за исключением копирования, конструкторов и операторов | и |=). Это упрощает переход от сценариев, основанных на словарях, к сценариям, требующим постоянного хранения.

Поддерживаются два дополнительных метода:

Shelf.sync()

Запишите обратно все записи в кэш, если полка была открыта с параметром обратная запись, равным True. Также очистите кэш и, если возможно, синхронизируйте постоянный словарь на диске. Это вызывается автоматически, когда полка закрывается с помощью close().

Shelf.close()

Синхронизируйте и закройте постоянный объект dict. Операции с закрытой полкой завершатся ошибкой с ValueError.

См.также

Persistent dictionary recipe с широко поддерживаемыми форматами хранения и скоростью работы собственных словарей.

Ограничения

  • Выбор того, какой пакет базы данных будет использоваться (например, dbm.ndbm или dbm.gnu), зависит от того, какой интерфейс доступен. Поэтому открывать базу данных напрямую с помощью dbm небезопасно. База данных также (к сожалению) подвержена ограничениям dbm, если она используется - это означает, что (выбранное представление) объектов, хранящихся в базе данных, должно быть довольно небольшим, и в редких случаях коллизии ключей могут привести к отказу базы данных в обновлении.

  • Модуль shelve не поддерживает одновременный доступ для чтения/записи к отложенным объектам. (Множественный одновременный доступ для чтения безопасен.) Когда в программе есть открытая для записи полка, ни одна другая программа не должна открывать ее для чтения или записи. Для решения этой проблемы можно использовать блокировку файлов Unix, но в разных версиях Unix она различается и требует знаний об используемой реализации базы данных.

  • В Mac OS dbm.ndbm может незаметно повредить файл базы данных при обновлении, что может привести к серьезным сбоям при попытке чтения из базы данных.

class shelve.Shelf(dict, protocol=None, writeback=False, keyencoding='utf-8')

Подкласс collections.abc.MutableMapping, который хранит выбранные значения в объекте dict.

По умолчанию для сериализации значений используются pickles, созданные с помощью pickle.DEFAULT_PROTOCOL. Версию протокола pickle можно указать с помощью параметра protocol. Описание протоколов pickle приведено в документации pickle.

Если параметр writeback равен True, объект будет хранить кэш всех записей, к которым был получен доступ, и записывать их обратно в dict во время синхронизации и закрытия. Это позволяет выполнять естественные операции с изменяемыми записями, но может потреблять гораздо больше памяти и приводить к длительной синхронизации и закрытию.

Параметр keyencoding - это кодировка, используемая для кодирования ключей перед их использованием с базовым dict.

Объект Shelf также может использоваться в качестве контекстного менеджера, и в этом случае он будет автоматически закрыт при завершении блока with.

Изменено в версии 3.2: Добавлен параметр keyencoding; ранее ключи всегда кодировались в UTF-8.

Изменено в версии 3.4: Добавлена поддержка контекстного менеджера.

Изменено в версии 3.10: pickle.DEFAULT_PROTOCOL теперь используется в качестве протокола pickle по умолчанию.

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, который принимает имя файла вместо объекта, подобного 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

См.также

Модуль dbm

Универсальный интерфейс для баз данных в стиле dbm.

Модуль pickle

Сериализация объектов, используемая shelve.

Вернуться на верх