shelve — Python object persistence

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


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

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

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

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

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

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

Примечание

Не полагайтесь на то, что полка будет закрыта автоматически; всегда вызывайте 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.

См.также

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

Ограничения

  • Выбор того, какой пакет базы данных будет использоваться (например, 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, созданные с помощью 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, который принимает имя файла вместо диктоподобного объекта. Базовый файл будет открыт с помощью 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.

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