Хотя файловые системы DBM должны проделать некоторую работу по отображению сохраняемых данных в ключи для быстрого извлечения (технически для сохранения данных в файлах они обычно используют прием, называемый хе широ ва ни ем), сценариям не приходится беспокоиться о том, что происходит за кулисами. В действительности файлы DBM являются одним из простейших способов сохранения информации в Python — файлы DBM ведут себя настолько сходно со словарями, размещаемыми в памяти, что можно забыть о том, что в самом деле вы работаете с файлом. Например, если есть объект файла DBM:
• Операция индексирования по ключу извлекает данные из файла.
• Операция присвоения по индексу сохраняет данные в файле.
Объекты файлов DBM поддерживают также стандартные методы словарей, такие как выборка и проверка по списку ключей и удаление по ключу. Сама библиотека DBM скрыта за этой простой моделью. Ввиду простоты перейдем прямо к интерактивному примеру, в котором создается файл DBM и демонстрируется, как работает интерфейс:
C:\…\PP4E\Dbase> python
>>> import dbm # получить интерфейс: bsddb, gnu, ndbm, dumb
>>> file = dbm.open(‘movie‘, ‘c‘) # создать файл DBM с именем ‘movie‘
>>> file[‘Batman‘] = ‘Pow!’ # сохранить строку с ключом ‘Batman‘
>>> file.keys() # получить список ключей в файле
[b‘Batman‘]
>>> file[‘Batman‘] # извлечь значение по ключу ‘Batman‘
b’Pow!’
>>> who = [‘Robin’, ‘Cat-woman’, ‘Joker’]
>>> what = [‘Bang!’, ‘Splat!’, ‘Wham!’]
>>> for i in range(len(who)):
… file[who[i]] = what[i] # добавить еще 3 "записи"
>>> file.keys()
[b’Cat-woman’, b’Batman’, b’Joker’, b’Robin’]
>>> len(file), ‘Robin’ in file, file[‘Joker’]
(4, True, b‘Wham!’)
>>> file.close() # иногда требуется закрывать явно
На практике при импорте стандартного модуля dbm автоматически загружается тот интерфейс DBM, который доступен вашему интерпретатору Python (опробуются различные альтернативы в строго определенном порядке), а при открытии нового файла DBM создается один или более внешних файлов с именами, начинающимися со строки ‘movie’ (о деталях будет сказано чуть ниже). Но после импорта и открытия файл DBM фактически неотличим от словаря.
В сущности, объект с именем file в этом примере можно представить себе как словарь, отображаемый во внешний файл с именем movie. Единственные очевидные отличия состоят в том, что ключами могут быть только строки (а не произвольные неизменяемые объекты), и для доступа к данным необходимо открывать, а после изменения данных — закрывать файл.
Однако в отличие от обычных словарей, содержимое file сохраняется в перерыве между запусками программы Python. Если мы потом вернемся и заново запустим Python, наш словарь будет по-прежнему доступен. Файлы DBM похожи на словари, которые требуется открывать:
C:\…\PP4E\Dbase> python
>>> import dbm
>>> file = dbm.open(‘movie‘, ‘c‘) # открыть существующий файл DBM
>>> file[‘Batman‘] b‘Pow!’
>>> file.keys() # метод keys возвращает список ключей
[b’Cat-woman’, b’Batman’, b’Joker’, b’Robin’]
>>> for key in file.keys(): print(key, file[key])
…
b’Cat-woman’ b’Splat!’ b’Batman’ b’Pow!’ b’Joker’ b’Wham!’ b’Robin’ b’Bang!’
Обратите внимание, что при обращении к методу keys файлов DBM возвращается действительный список — здесь не показано, но метод values этих файлов, напротив, возвращает итерируемое представление, как при обращении к обычным словарям. Кроме того, файлы DBM всегда хранят ключи и значения в виде объектов bytes — интерпретация их в виде текста Юникода остается за клиентским приложением. При обращении к хранимым ключам или значениям в нашем программном коде мы можем использовать строки bytes или str — использование строк bytes позволяет сохранять ключи и значения в произвольных кодировках Юникода, тогда как при использовании объектов str они будут кодироваться в объекты bytes внутренней реализацией DBM с применением кодировки UTF-8.
Однако при необходимости мы всегда можем декодировать строки bytes в строки str для отображения, и подобно словарям файлы DBM имеют итератор по ключам. Кроме того, операции присваивания и удаления по ключу изменяют содержимое файла DBM, и после внесения изменений необходимо закрывать файл (это гарантирует сохранение изменений на диске):
>>> for key in file: print(key.decode(), file[key].decode())
…
Cat-woman Splat!
Batman Pow!
Joker Wham!
Robin Bang!
>>> file[‘Batman’] = ‘Ka-Boom!’ # изменить значение ключа Batman
>>> del file[‘Robin‘] # удалить запись Robin
>>> file.close() # закрыть после изменений
За исключением необходимости импортировать интерфейс и откры- вать/закрывать файл DBM, программам на языке Python не требуется ничего знать собственно о DBM. Модули DBM добиваются такой интеграции, перегружая операции индексирования и переадресуя их более простым библиотечным инструментам. Но глядя на этот программный код, вы никогда бы этого не узнали — файлы DBM выглядят как обычные словари Python, хранящиеся во внешних файлах. Произведенные в них изменения сохраняются неограниченно долго:
C:\…\PP4E\Dbase> python
>>> import dbm # открыть файл DBM еще раз
>>> file = dbm.open(‘movie’, ‘c’)
>>> for key in file: print(key.decode(), file[key].decode())
…
Cat-woman Splat!
Batman Ka-Boom!
Joker Wham!
Как видите, проще уже некуда. В табл. 17.1 перечислены наиболее частые операции с файлами DBM. Если открыт такой файл, он обрабатывается так, как если бы был словарем Python, находящимся в памяти. Выборка элементов осуществляется индексированием объекта файла по ключу, а запись — путем присвоения по ключу.
Табли ца 17.1. Опера ции с файла ми DBM
Программный код Python |
Действие |
Описание |
import dbm |
Импорт |
Получить реализацию DBM |
file=dbm.open(‘filename’, ‘c’) |
Открытие |
Создать или открыть существующий файл DBM для ввода-вывода |
file[‘key’] = ‘value’ |
Запись |
Создать или изменить запись с ключом key |
value = file[‘key’] |
Выборка |
Загрузить значение из записи с ключом key |
count = len(file) |
Размер |
Получить количество записей |
index = file.keys() |
Индекс |
Получить список (не представление) ключей |
Программный код Python |
Действие |
Описание |
found = ‘key’ in file |
Запрос |
Проверить наличие записи с ключом key |
del file[‘key’] |
Удаление |
Удалить запись с ключом key |
for key in file: |
Итерации |
Выполнить итерации по имеющимся ключам |
file.close() |
Закрытие |
Закрыть вручную, требуется не всегда |
Использованная литература:
Марк Лутц — Программирование на Python, 4-е издание, II том, 2011