Модули pickle, shelve и dbm
Возможность сохранения объектов во всех версиях Python обеспечивают три
модуля в стандартной библиотеке:
pickle
Преобразует произвольные объекты на языке Python в строку байтов и обратно.
dbm (в Python 2.6 называется anydbm)
Реализует сохранение строк в файлах, обеспечивающих возможность обращения по ключу.
shelve
Использует первые два модуля, позволяя сохранять объекты в файлах хранилищах, обеспечивающих возможность обращения по ключу.
Запись объектов в БД
from person import Person, Manager # Импортирует наши классы bob = Person(‘Bob Smith’) # Создание объектов для сохранения sue = Person(‘Sue Jones’, job=’dev’, pay=100000) tom = Manager(‘Tom Jones’, 50000) import shelve db = shelve.open(‘persondb’) # Имя файла хранилища for object in (bob, sue, tom): # В качестве ключа использовать атрибут name db[object.name] = object # Сохранить объект в хранилище db.close() # Закрыть после внесения изменений
Чтение объектов из БД
>>> import shelve >>> db = shelve.open(‘persondb’) # Открыть хранилище >>> len(db) # В хранилище содержится три ‘записи’ 3 >>> list(db.keys()) # keys – это оглавление [‘Tom Jones’, ‘Sue Jones’, ‘Bob Smith’] # Функция list используется, чтобы # получить список в 3.0 >>> bob = db[‘Bob Smith’] # Извлечь объект bob по ключу >>> print(bob) # Вызовет __str__ из AttrDisplay [Person: job=None, name=Bob Smith, pay=0] >>> bob.lastName() # Вызовет lastName из Person ‘Smith’ >>> for key in db: # Итерации, извлечение, вывод print(key, ‘=>’, db[key]) Tom Jones => [Manager: job=mgr, name=Tom Jones, pay=50000] Sue Jones => [Person: job=dev, name=Sue Jones, pay=100000] Bob Smith => [Person: job=None, name=Bob Smith, pay=0]
Благодаря такому поведению после загрузки экземпляры классов автоматически обретают поведение своего класса. Мы должны импортировать наши классы, только если необходимо создавать новые экземпляры, но не для работы с существующими. Такая особенность поведения влечет за собой следующие последствия:
- Недостаток заключается в том, что позднее, когда выполняется загрузка экземпляров, классы и их модули должны быть доступны для импортирования. Если говорить более формально, классы сохраняемых объектов должны быть определены на верхнем уровне модуля, который находится в одном из каталогов в пути поиска sys.path (и не должны находиться в модуле __main__ сценария, если только они не используются только в пределах этого модуля). Из-за этих требований, предъявляемых к внешним файлам модулей, в некоторых приложениях для сохранения используются более простые объекты, такие как словари или списки, особенно когда они передаются другим приложениям через Интернет.
- Преимущество заключается в том, что изменения в реализации класса автоматически будут восприняты экземплярами после их загрузки – часто нет никакой необходимости обновлять сохраненные объекты, потому что обычно изменения касаются только реализации методов класса.
Обновление данных в БД
# Файл updatedb.py: обновляет объект класса Person в базе данных import shelve db = shelve.open(‘persondb’) # Открыть хранилище в файле с указанным именем for key in sorted(db): # Обойти и отобразить объекты в базе данных print(key, ‘\t=>’, db[key]) # Вывод в требуемом формате sue = db[‘Sue Jones’] # Извлечь объект по ключу sue.giveRaise(.10) # Изменить объект в памяти вызовом метода db[‘Sue Jones’] = sue # Присвоить по ключу, # чтобы обновить объект в хранилище db.close() # Закрыть после внесения изменений
Благодаря тому, что при запуске этот сценарий выводит содержимое базы данных, мы можем запустить его несколько раз и увидеть, как изменяются наши
объекты. Ниже приводятся результаты нескольких запусков сценария, где можно наблюдать, как каждый раз повышается зарплата sue (отличный сценарий для sue…):
c:\misc> updatedb.py Bob Smith => [Person: job=None, name=Bob Smith, pay=0] Sue Jones => [Person: job=dev, name=Sue Jones, pay=100000] Tom Jones => [Manager: job=mgr, name=Tom Jones, pay=50000] c:\misc> updatedb.py Bob Smith => [Person: job=None, name=Bob Smith, pay=0] Sue Jones => [Person: job=dev, name=Sue Jones, pay=110000] Tom Jones => [Manager: job=mgr, name=Tom Jones, pay=50000]