Выбрать главу

Интерфейс модуля shelve так же прост, как и интерфейс модуля pickle: хранилища, создаваемые модулем shelve, идентичны словарям с дополнительными методами open и close. В программном коде объекты хранилищ действительно выглядят, как словари, содержимое которых сохраняется после завершения программы. А все операции по отображению содержимого хранилища в файл и из файла выполняются интерпретатором Python. Например, сценарий в примере 1.11 демонстрирует, как можно сохранить объекты из словаря в хранилище, созданном с помощью модуля shelve.

Пример 1.11. PP4E\Preview\make_db_shelve.py

from initdata import bob, sue import shelve

db = shelve.open(‘people-shelve’) db[‘bob’] = bob db[‘sue’] = sue db.close()

Этот сценарий создаст в текущем каталоге один или более файлов, имена которых начинаются с префикса people-shelve (в ОС Windows, под управлением Python 3.1, сценарий создаст файлы people-shelve.bak, people-shelve.dat и people-shelve.dir). Вы не должны удалять эти файлы (они составляют вашу базу данных!), а чтобы получить доступ к этому хранилищу в других сценариях, необходимо использовать то же самое имя базы. Сценарий в примере 1.12, например, повторно открывает хранилище и последовательно извлекает хранящиеся в нем записи.

Пример 1.12. PP4E\Preview\dump_db_shelve.py

import shelve

db = shelve.open(‘people-shelve’) for key in db:

print(key, ‘=>\n ‘, db[key]) print(db[‘sue’][‘name’]) db.close()

Мы по-прежнему имеем словарь словарей, но на этот раз словарем верхнего уровня является хранилище, отображаемое в файл. Всякий раз, когда происходит обращение к элементу в хранилище, модуль shelve выполняет необходимые операции с файловой системой, обеспечивающей доступ по ключу, и использует модуль pickle для сериализации и десериализации объектов. Однако, с точки зрения программиста, хранилище - это всего лишь словарь, обладающий возможностью сохраняться между вызовами программы. Сценарий в примере 1.13 демонстрирует, как можно реализовать изменение данных в хранилище.

Пример 1.13. PP4E\Preview\update_db_shelve.py

from initdata import tom import shelve

db = shelve.open(‘people-shelve’)

sue = db[‘sue’]    # извлекает объект sue

sue[‘pay’] *= 1.50

db[‘sue’] = sue    # изменяет объект sue

db[‘tom’] = tom    # добавляет новую запись

db.close()

Обратите внимание, что в этом примере сначала по ключу извлекается объект sue, затем он изменяется в памяти и снова сохраняется в хранилище по ключу. Так действуют хранилища по умолчанию, однако более совершенные системы хранения, такие как ZODB, о которой рассказывается в главе 17, могут действовать иначе. Как мы узнаем позднее, метод shelve.open в подобных системах имеет дополнительный именованный аргумент writeback. Если в этом аргументе передать значение True, все загруженные записи будут сохраняться в кэше и автоматически записываться обратно в файл при закрытии хранилища. Благодаря этому не требуется вручную записывать изменения обратно в хранилище, но при этом увеличивается потребление памяти, а сама операция закрытия может занимать продолжительное время.

Обратите также внимание на необходимость явного закрытия хранилища. Нам не требуется указывать флаги режимов в вызове метода shelve. open (по умолчанию он создает новое хранилище, если это необходимо, и открывает существующее хранилище для чтения и записи), однако некоторые механизмы, обеспечивающие доступ к содержимому файлов по ключу, требуют вызова метода close, чтобы сбросить на диск выходные буферы с изменениями.

Наконец, ниже приводится пример запуска сценариев, опирающихся на использование модуля shelve, которые создают, изменяют и извлекают записи. Записи по-прежнему реализованы как словари, но сама база данных теперь является хранилищем, напоминающим словарь, который автоматически сохраняет свое содержимое в файле:

...\PP4E\Preview> python make_db_shelve.py

...\PP4E\Preview> python dump_db_shelve.py

bob =>

{‘pay’: 30000, ‘job’: ‘dev’, ‘age’: 42, ‘name’: ‘Bob Smith’}

sue =>

{‘pay’: 40000, ‘job’: ‘hdw’, ‘age’: 45, ‘name’: ‘Sue Jones’}

Sue Jones

...\PP4E\Preview> python update_db_shelve.py

...\PP4E\Preview> python dump_db_shelve.py

bob =>

{‘pay’: 30000, ‘job’: ‘dev’, ‘age’: 42, ‘name’: ‘Bob Smith’}

sue =>

{‘pay’: 60000.0, ‘job’: ‘hdw’, ‘age’: 45, ‘name’: ‘Sue Jones’}

tom =>

{‘pay': 0, ‘job': None, ‘age': 50, ‘name': ‘Tom'}

Sue Jones