Работа модуля pickle с отдельными записями
Как упоминалось выше, один из потенциальных недостатков примеров, представленных в этом разделе до настоящего момента, состоит в том, что они могут оказаться слишком медленными при работе с очень большими базами данных: так как для изменения единственной записи необходимо загружать и сохранять базу данных целиком, при таком решении значительная часть времени будет тратиться впустую. Мы могли бы избежать этого, предусмотрев сохранение каждой записи базы данных в отдельном файле. Следующие три примера демонстрируют, как это можно реализовать, - сценарий из примера 1.8 сохраняет каждую запись в отдельном файле, где в качестве имени файла используется уникальный ключ записи, к которому добавляется расширение .pkl (он создает файлы bob.pkl, sue.pkl и tom.pkl в текущем рабочем каталоге).
Пример 1.8. PP4E\Preview\make_db_pickle_recs.py
from initdata import bob, sue, tom import pickle
for (key, record) in [(‘bob’, bob), (‘tom’, tom), (‘sue’, sue)]: recfile = open(key + ‘.pkl’, ‘wb’) pickle.dump(record, recfile) recfile.close()
Следующий сценарий, представленный в примере 1.9, выводит содержимое всей базы данных, используя модуль glob для подстановки имен файлов и тем самым для выбора всех файлов с расширением .pkl, присутствующих в текущем каталоге. Чтобы загрузить единственную запись, мы открываем файл этой записи и выполняем преобразование содержимого файла с помощью модуля pickle. Теперь, чтобы получить одну запись, нам необходимо загрузить файл единственной записи, а не всю базу данных.
Пример 1.9. PP4E\Preview\dump_db_pickle_recs.py
import pickle, glob
for filename in glob.glob(‘*.pkl’): # для ‘bob’,’sue’,’tom’
recfile = open(filename, ‘rb’) record = pickle.load(recfile) print(filename, ‘=>\n ‘, record)
suefile = open(‘sue.pkl’, ‘rb’)
print(pickle.load(suefile)[‘name’]) # извлечь имя Сью
Наконец, сценарий в примере 1.10 обновляет содержимое базы данных, извлекая запись из ее файла, изменяя объект в памяти и затем сохраняя его обратно в файл с помощью модуля pickle. На этот раз для внесения изменений необходимо извлечь и сохранить единственную запись, а не всю базу данных.
Пример 1.10. PP4E\Preview\update_db_pickle_recs.py
import pickle
suefile = open(‘sue.pkl’, ‘rb’)
sue = pickle.load(suefile)
suefile.close()
sue[‘pay’] *= 1.10
suefile = open(‘sue.pkl’, ‘wb’)
pickle.dump(sue, suefile)
suefile.close()
Ниже приводится пример запуска сценариев, реализующих решение, когда каждая запись сохраняется в отдельном файле. Результаты получаются те же, что и прежде, но теперь уникальные ключи в базе данных играют роль имен файлов. При такой реализации файловая система превращается в своеобразный словарь верхнего уровня - имена файлов обеспечивают прямой доступ к отдельным записям.
...\PP4E\Preview> python make_db_pickle_recs.py ...\PP4E\Preview> python dump_db_pickle_recs.py
bob.pkl =>
{‘pay’: 30000, ‘job’: ‘dev’, ‘age’: 42, ‘name’: ‘Bob Smith’} sue.pkl =>
{‘pay’: 40000, ‘job’: ‘hdw’, ‘age’: 45, ‘name’: ‘Sue Jones’} tom.pkl =>
{‘pay’: 0, ‘job’: None, ‘age’: 50, ‘name’: ‘Tom’}