Я ищу совет о методах реализации сохранения объектов в Python. Чтобы быть более точным, я хочу уметь связывать объект Python с файлом таким образом, что любой процесс Python, который открывает представление этого файла, имеет одинаковую информацию, любой процесс может изменить его объект, и изменения будут распространяться на другие процессы, и даже если все процессы, "сохраняющие" объект, будут закрыты, файл останется и может быть снова открыт другим процессом.
Я нашел для себя три основных кандидата в моем распределении Python - anydbm, pickle и shelve (dbm оказался идеальным, но это Unix-only, и я нахожусь в Windows). Однако все они имеют недостатки:
- anydbm может обрабатывать только словарь строковых значений (я хочу хранить список словарей, все из которых имеют строковые ключи и строковые значения, хотя в идеале я бы искал модуль без ограничений типа)
- shelve требует, чтобы файл был повторно открыт до того, как изменения распространились - например, если два процесса A и B загружают один и тот же файл (содержащий полки пустой список), а A добавляет элемент в список и вызывает sync(), B все равно будет видеть, что список пуст, пока он не перезагрузит файл.
- pickle (модуль, который я сейчас использую для моей тестовой реализации) имеет такое же "требование перезагрузки", как и отложенное, а также не перезаписывает предыдущие данные - если процесс 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, и отредактировал поведение дампа и нагрузки, чтобы они использовали повторяющиеся чтения, о которых я упоминал выше, - но мне трудно поверить, что эта проблема никогда не возникала, и были исправлены более талантливыми программистами. Более того, эти повторяющиеся чтения кажутся мне неэффективными (хотя я должен признать, что мое знание сложности операции ограничено, и возможно, что эти повторные чтения продолжаются "за кулисами" в других, по-видимому, более плавных модулях, таких как полка). Поэтому я пришел к выводу, что мне не хватает кода, который бы разрешил проблему для меня. Я был бы признателен, если бы кто-нибудь мог указать мне в правильном направлении или дать рекомендации по реализации.