Постоянство объектов в Python

Мне нужен совет о методах реализации сохраняемости объектов в Python.Чтобы быть более точным, я хочу иметь возможность связать объект Python с файлом таким образом, чтобы любой процесс Python, открывающий представление этого файла, совместно использовал одну и ту же информацию, любой процесс мог изменять свой объект, и изменения распространялись на другие процессы, и даже если все процессы, «хранящие» объект, будут закрыты, файл останется и может быть повторно открыт другим процессом.

В моем дистрибутиве Python я нашел трех основных кандидатов на это — anydbm, pickle и shelve (dbm оказался идеальным, но он только для Unix, а я на Windows). Однако все они имеют недостатки:

  • anydbm может обрабатывать только словарь строковых значений (я хочу хранить список словарей, каждый из которых имеет строковые ключи и строковые значения, хотя в идеале я бы искал модуль без ограничения типа)
  • shelve требует, чтобы файл был повторно открыт перед распространением изменений — например, если два процесса A и B загружают один и тот же файл (содержащий отложенный пустой список), а A добавляет элемент в список и вызывает sync(), B по-прежнему будет видеть список пустым, пока не перезагрузит файл.
  • pickle (модуль, который я сейчас использую для своей тестовой реализации) имеет то же «требование перезагрузки», что и shelve, а также не перезаписывает предыдущие данные — если процесс A выгружает пятнадцать пустых строк в файл, а затем строку ' hello», процесс B должен будет загрузить файл шестнадцать раз, чтобы получить строку «hello».В настоящее время я решаю эту проблему, предваряя любую операцию записи повторным чтением до конца файла («очищая планшет перед записью») и повторяя каждую операцию чтения до конца файла, но я чувствую, что должно быть лучший способ.

Мой идеальный модуль будет вести себя следующим образом (где «A>>>» представляет код, выполняемый процессом A, а «B>>>» — код, выполняемый процессом B):

A>>> import imaginary_perfect_module as mod
B>>> import imaginary_perfect_module as mod
A>>> d = mod.load('a_file') 
B>>> d = mod.load('a_file')
A>>> d
{}
B>>> d
{}
A>>> d[1] = 'this string is one'
A>>> d['ones'] = 1   #anydbm would sulk here
A>>> d['ones'] = 11 
A>>> d['a dict'] = {'this dictionary' : 'is arbitrary', 42 : 'the answer'}
B>>> d['ones']   #shelve would raise a KeyError here, unless A had called d.sync() and B had reloaded d
11    #pickle (with different syntax) would have returned 1 here, and then 11 on next call
(etc. for B)

Я мог добиться такого поведения, создав свой собственный модуль, использующий pickle, и редактирование поведения дампа и загрузки, чтобы они использовали повторные чтения, о которых я упоминал выше, но мне трудно поверить, что эта проблема никогда не возникала и не решалась более талантливыми программистами раньше. Более того, эти повторные чтения кажутся мне неэффективными (хотя я должен признать, что мои знания о сложности операций ограничены, и возможно, что эти повторные чтения происходят «за кулисами» в других, казалось бы, более гладких модулях, таких как полка). Поэтому я делаю вывод, что мне не хватает какого-то модуля кода, который решил бы проблему за меня. Я был бы признателен, если бы кто-нибудь мог указать мне правильное направление или дать совет по реализации.

11
задан scubbo 31 May 2012 в 09:28
поделиться