Python Language
откладывать в долгий ящик
Поиск…
Вступление
Shelve - это модуль python, используемый для хранения объектов в файле. Модуль полки реализует постоянное хранилище для произвольных объектов Python, которые можно мариновать, используя словарь-подобный API. Модуль полки может использоваться как простая постоянная память для объектов Python, когда реляционная база данных переполнена. Доступ к полкам осуществляется с помощью клавиш, как и со словарем. Значения подсчитываются и записываются в базу данных, созданную и управляемую anydbm.
замечания
Примечание. Не полагайтесь на закрывающуюся полку автоматически; всегда вызывайте close()
явно, когда вам это больше не нужно, или используйте shelve.open()
в качестве менеджера контекста:
with shelve.open('spam') as db:
db['eggs'] = 'eggs'
Предупреждение:
Поскольку модуль shelve
опирается на pickle
, небезопасно загружать полку из ненадежного источника. Как и при рассоле, загрузка полки может выполнять произвольный код.
ограничения
1 . Выбор того, какой пакет базы данных будет использоваться (например, dbm.ndbm или dbm.gnu), зависит от того, какой интерфейс доступен. Поэтому небезопасно открывать базу данных напрямую с помощью dbm. База данных также (к сожалению) зависит от ограничений dbm, если она используется - это означает, что (маринованное представление) объекты, хранящиеся в базе данных, должны быть довольно маленькими, и в редких случаях столкновения с ключами могут привести к тому, что база данных будет отказаться от обновлений.
2. Модуль полки не поддерживает одновременный доступ на чтение и запись к закрытым объектам. (Несколько одновременных доступов для чтения безопасны.) Когда у программы есть открытая полка для записи, никакая другая программа не должна открывать ее для чтения или записи. Для решения этой проблемы можно использовать блокировку файлов Unix, но это отличается от версий Unix и требует знаний о используемой реализации базы данных.
Пример кода для полки
Чтобы отложить объект, сначала импортируйте модуль, а затем назначьте значение объекта следующим образом:
import shelve
database = shelve.open(filename.suffix)
object = Object()
database['key'] = object
Чтобы суммировать интерфейс (ключ - строка, данные - произвольный объект):
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
Создание нового шельфа
Самый простой способ использования полки - это класс DbfilenameShelf . Он использует anydbm для хранения данных. Вы можете использовать класс напрямую или просто вызвать shelve.open () :
import shelve
s = shelve.open('test_shelf.db')
try:
s['key1'] = { 'int': 10, 'float':9.5, 'string':'Sample data' }
finally:
s.close()
Чтобы снова получить доступ к данным, откройте полку и используйте ее как словарь:
import shelve
s = shelve.open('test_shelf.db')
try:
existing = s['key1']
finally:
s.close()
print existing
Если вы запускаете оба примера сценариев, вы должны увидеть:
$ python shelve_create.py
$ python shelve_existing.py
{'int': 10, 'float': 9.5, 'string': 'Sample data'}
Модуль dbm не поддерживает одновременное использование нескольких приложений, записываемых в одну и ту же базу данных. Если вы знаете, что ваш клиент не будет изменять полку, вы можете сообщить полке, чтобы открыть базу данных только для чтения.
import shelve
s = shelve.open('test_shelf.db', flag='r')
try:
existing = s['key1']
finally:
s.close()
print existing
Если ваша программа пытается изменить базу данных, пока она открыта только для чтения, генерируется исключение ошибки доступа. Тип исключения зависит от модуля базы данных, выбранного anydbm при создании базы данных.
Write-назад
Полки не отслеживают изменения изменчивых объектов по умолчанию. Это означает, что если вы измените содержимое элемента, хранящегося на полке, вы должны явно обновить полку, сохранив элемент снова.
import shelve
s = shelve.open('test_shelf.db')
try:
print s['key1']
s['key1']['new_value'] = 'this was not here before'
finally:
s.close()
s = shelve.open('test_shelf.db', writeback=True)
try:
print s['key1']
finally:
s.close()
В этом примере словарь в 'key1' не сохраняется снова, поэтому, когда полка снова открывается, изменения не сохранились.
$ python shelve_create.py
$ python shelve_withoutwriteback.py
{'int': 10, 'float': 9.5, 'string': 'Sample data'}
{'int': 10, 'float': 9.5, 'string': 'Sample data'}
Чтобы автоматически улавливать изменения изменчивых объектов, хранящихся на полке, откройте полку с включенной обратной записью. Флаг обратной записи заставляет полку запоминать все объекты, извлеченные из базы данных, используя кеш в памяти. Каждый объект кэша также записывается обратно в базу данных, когда полка закрыта.
import shelve
s = shelve.open('test_shelf.db', writeback=True)
try:
print s['key1']
s['key1']['new_value'] = 'this was not here before'
print s['key1']
finally:
s.close()
s = shelve.open('test_shelf.db', writeback=True)
try:
print s['key1']
finally:
s.close()
Хотя это уменьшает вероятность ошибки программиста и может сделать сохранение объекта более прозрачным, использование режима обратной записи может быть нежелательным в любой ситуации. Кэш потребляет дополнительную память, пока полка открыта, и приостановка записи каждого кэшированного объекта обратно в базу данных, когда она закрыта, может занять дополнительное время. Поскольку нет способа узнать, были ли изменены кешированные объекты, все они записаны обратно. Если ваше приложение читает данные больше, чем пишет, обратная связь добавит больше накладных расходов, чем вы могли бы захотеть.
$ python shelve_create.py
$ python shelve_writeback.py
{'int': 10, 'float': 9.5, 'string': 'Sample data'}
{'int': 10, 'new_value': 'this was not here before', 'float': 9.5, 'string': 'Sample data'}
{'int': 10, 'new_value': 'this was not here before', 'float': 9.5, 'string': 'Sample data'}