Рубрики
Без рубрики

полка – постоянное хранилище объектов

Автор оригинала: Doug Hellmann.

Цель:

Модуль полки реализует постоянное хранилище для произвольные объекты Python, которые можно мариновать, используя словарь-подобный API.

Модуль shelve может использоваться как простой вариант постоянного хранения для объектов Python, когда реляционная база данных не требуется. Доступ к полке осуществляется клавишами, как и со словарем. Значения собираются и записываются в базу данных, созданную и управляемую dbm.

Создание новой полки

Самый простой способ использовать shelve – использовать класс DbfilenameShelf . Он использует dbm для хранения данных. Класс может использоваться напрямую или

shelve_create.py

import shelve

with shelve.open('test_shelf.db') as s:
    s['key1']  {
        'int': 10,
        'float': 9.5,
        'string': 'Sample data',
    }

Чтобы снова получить доступ к данным, откройте полку и используйте ее как

shelve_existing.py

import shelve

with shelve.open('test_shelf.db') as s:
    existing  s['key1']

print(existing)

Выполнение обоих примеров сценариев дает следующий результат.

$ python3 shelve_create.py
$ python3 shelve_existing.py

{'int': 10, 'float': 9.5, 'string': 'Sample data'}

Модуль dbm не поддерживает одновременную запись нескольких приложений в одну и ту же базу данных, но поддерживает одновременных клиентов только для чтения. Если клиент не будет изменять полку, скажите shelve открыть базу данных.

shelve_readonly.py

import dbm
import shelve

with shelve.open('test_shelf.db', flag'r') as s:
    print('Existing:', s['key1'])
    try:
        s['key1']  'new value'
    except dbm.error as err:
        print('ERROR: {}'.format(err))

Если программа пытается изменить базу данных, когда она открыта только для чтения, генерируется исключение ошибки доступа. Тип исключения зависит от базы данных

$ python3 shelve_readonly.py

Existing: {'int': 10, 'float': 9.5, 'string': 'Sample data'}
ERROR: cannot add item to database

Ответная запись

По умолчанию полки не отслеживают изменения изменчивых объектов. Это означает, что при изменении содержимого элемента, хранящегося на полке, полка должна быть явно обновлена путем повторного сохранения всего элемента.

shelve_withoutwriteback.py

import shelve

with shelve.open('test_shelf.db') as s:
    print(s['key1'])
    s['key1']['new_value']  'this was not here before'

with shelve.open('test_shelf.db', writebackTrue) as s:
    print(s['key1'])

В этом примере словарь в 'key1' больше не сохраняется, поэтому при повторном открытии полки изменения не сохраняются.

$ python3 shelve_create.py
$ python3 shelve_withoutwriteback.py

{'int': 10, 'float': 9.5, 'string': 'Sample data'}
{'int': 10, 'float': 9.5, 'string': 'Sample data'}

Чтобы автоматически отслеживать изменения в изменчивых объектах, хранящихся на полке, откройте ее с включенной обратной записью. Флаг обратной записи заставляет полку запоминать все объекты, извлеченные из базы данных с использованием кеша в памяти. Каждый объект кеша также записывается обратно в базу данных, когда полка закрывается.

shelve_writeback.py

import shelve
import pprint

with shelve.open('test_shelf.db', writebackTrue) as s:
    print('Initial data:')
    pprint.pprint(s['key1'])

    s['key1']['new_value']  'this was not here before'
    print('\nModified:')
    pprint.pprint(s['key1'])

with shelve.open('test_shelf.db', writebackTrue) as s:
    print('\nPreserved:')
    pprint.pprint(s['key1'])

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

$ python3 shelve_create.py
$ python3 shelve_writeback.py

Initial data:
{'float': 9.5, 'int': 10, 'string': 'Sample data'}

Modified:
{'float': 9.5,
 'int': 10,
 'new_value': 'this was not here before',
 'string': 'Sample data'}

Preserved:
{'float': 9.5,
 'int': 10,
 'new_value': 'this was not here before',
 'string': 'Sample data'}

Конкретные типы полок

Все предыдущие примеры использовали реализацию полки по умолчанию. Использование shelve.open () вместо одной из реализаций полки напрямую является распространенным шаблоном использования, особенно если не имеет значения, какой тип базы данных используется для хранения данных. Однако бывают случаи, когда важен формат базы данных. В таких ситуациях используйте напрямую DbfilenameShelf или BsdDbShelf или даже подкласс Shelf для настраиваемого

Смотрите также