Pickle, shelve, dbm

Данная заметка вкратце о сериализации данных в стандартной библиотеке python с помощью модуля pickle, shelve и dbm

pickle

Предоставляет преобразование объектов python в последовтаельность байтов (сериализацию), что позволяет передать поток байтов в другой процесс или сохранить на диске, а затем реконструировать из этого исходный объект. Безопасность хранения не гарантируется.

Помимо кодирования/декодирования методами dumps()/loads(), возвращающих байтовый объект, предоставляется работа с файловыми потоками - это, в частности, позволяет писать несколько объектов, а затем читать их, не зная заранее количество и размеры. См. пример

Важно! При работе с пользовательскими классами, пользовательский класс должен быть виден в пространстве имен процесса, выполняющего чтение сериализованного объекта. Если этого не сделать - будет поднята ошибка AttributeError. Кроме того, не все объекты могут быть сериализованы - к таким объектам относятся сокеты, дескрипторы, подключения к бд и другие объекты с состоянием времени выполнения, зависимым от операционной системы или другого процесса. Для таких объектов можно определить __getstate__() и __setstate__() для возврата состояния экземпляра, подлежащего сериализации. Циклическими ссылками модуль pickle управляет самостоятельно

shelve

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

Создание хранилища осуществляется через shelve.open() - задается ключ, которому передается объект. Т.к. реализация на dbm, то запись в один и тот же файл несколькими процессами одновременно не поддерживается, но возможен параллельный доступ для чтения. Чтобы открыть бд только для чтения, надо передать соответствующий флаг:

with shelve.open('bdname.db', flag='r') as bd:
    ...

По умолчанию бд, созданная shelve не отслеживает измененения, происходящие во временных объектах. Это означает, что хранилище нужно явно обновлять, если переданный в него объект изменился. Чтобы обеспечить автообновление, можно установить флаг writeback=True - это приведет к тому, чт ов кэш будут помещаться все объекты, извлекаемые из хранилища, а при закрытии бд, эти объекты будут записываться. Минусом такого подхода является то, что возникает переасход памяти и тормозится исполнение приложения в момент записи. Чтобы избежать данной проблемы, необходимо извлекать в память объект из дб, вносить в него изменения и производить перезапись.

d = shelve.open(filename)

# 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

dbm

Предоставляет доступ к юниксовским dbm-базам: данные хранятся в виде строк, ассоциированных со строковыми ключами. Модуль поставляется с несколькими типами доступных бд, дефолтная завист от конкретной реализации платформы. Смотри доку как выбрать бд, помимо дефолтной.

>>> На главную