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-базам: данные хранятся в виде строк, ассоциированных со строковыми ключами. Модуль поставляется с несколькими типами доступных бд, дефолтная завист от конкретной реализации платформы. Смотри доку как выбрать бд, помимо дефолтной.