Синхронизация данных в памяти с файлом для долго работающего скрипта Python - PullRequest
2 голосов
/ 24 ноября 2010

У меня есть скрипт Python (2.7), который действует как сервер, и поэтому он будет работать в течение очень длительного периода времени.В этом сценарии есть несколько значений, которые нужно отслеживать, и которые могут изменяться в любое время в зависимости от клиентского ввода.

В идеале я должен сохранить структуру данных Python (со значениями типов * 1003).*, list, unicode, int и float - JSON, в основном) в памяти, что позволяет мне обновлять его так, как я хочу (за исключением ссылки на любой из экземпляров ссылочного типа более одного раза), сохраняя при этом эти данныеобновленный в удобочитаемом файле, так что даже если вилка питания была отключена, сервер мог просто запуститься и продолжить работу с теми же данными.

Я знаю, что в основном говорю обазы данных, но данные, которые я храню, будут очень простыми и, вероятно, большую часть времени будут составлять менее 1 кБ, поэтому я ищу самое простое решение, которое может обеспечить описанную целостность данных.Есть ли хорошие библиотеки Python (2.7), которые позволяют мне делать что-то подобное?

Ответы [ 5 ]

4 голосов
/ 24 ноября 2010

Ну, поскольку вы знаете, что мы в основном говорим о базе данных, хотя и очень простой, вы, вероятно, не удивитесь, если я предлагаю вам взглянуть на модуль sqlite3 .

2 голосов
/ 24 ноября 2010

Я согласен, что вам не нужна полностью развернутая база данных, так как кажется, что все, что вам нужно, - это атомарная запись в файл . Вам нужно решить эту проблему в двух частях: сериализации / десериализации и атомарной записи.

Для первого раздела, json или pickle, вероятно, являются подходящими форматами для вас. Преимущество JSON заключается в том, что он удобочитаем для человека. Хотя не похоже, что это основная проблема, с которой вы столкнулись.

Как только вы сериализовали свой объект в строку, используйте следующую процедуру для атомарной записи файла на диск, предполагая, что один записывающий объект одновременно (по крайней мере, в POSIX, см. Ниже):

import os, platform
backup_filename = "output.back.json"
filename = "output.json"

serialised_str = json.dumps(...)
with open(backup_filename, 'wb') as f:
     f.write(serialised_str)
if platform.system() == 'Windows':
     os.unlink(filename)
os.rename(backup_filename, filename)

Хотя os.rename перезаписывает существующий файл и является атомарным в POSIX, к сожалению, в Windows это не так. В Windows существует вероятность того, что os.unlink удастся, но os.rename не удастся, что означает, что у вас есть только backup_filename и нет filename. Если вы ориентируетесь на Windows, вам нужно будет рассмотреть эту возможность, когда вы проверяете наличие filename.

Если существует возможность более чем одного параллельного писателя, вам нужно будет рассмотреть конструкцию синхронизации.

2 голосов
/ 24 ноября 2010

Любая причина для человека читаемое требование?

Я бы предложил посмотреть на sqlite для простого решения для базы данных или на pickle для простого способа сериализации объектов и записи их на диск. Хотя ни один из них не особенно удобен для чтения.

Другими вариантами являются JSON или XML, как вы намекали - используйте встроенный модуль json для сериализации объектов, а затем запишите их на диск. При запуске проверьте наличие этого файла и при необходимости загрузите данные.

Из документов :

>>> import json
>>> print json.dumps({'4': 5, '6': 7}, sort_keys=True, indent=4)
{
    "4": 5,
    "6": 7
}
1 голос
/ 24 ноября 2010

Поскольку вы упомянули, что ваши данные маленькие, я бы выбрал простое решение и использовал модуль pickle , который позволяет очень просто вывести объект python в строку .

Затем вы просто настраиваете Thread , который сохраняет ваш объект в файл в определенные промежутки времени.

Не "библиотечное" решение, но - если я понимаю вашетребования - достаточно простые для вас, чтобы не нуждаться в них.

РЕДАКТИРОВАТЬ: вы упомянули, что хотите охватить случай, когда проблема возникает во время самой записи, фактически превращая ее в атомарную транзакцию.В этом случае традиционным способом является использование «восстановления на основе журнала».По сути, это запись записи в файл журнала, в которой говорится, что «запись транзакции запущена», а затем запись «запись транзакции завершена», когда вы закончите.Если у «запущенного» нет соответствующего «коммита», то вы выполняете откат.

В этом случае я согласен, что вам может быть лучше с простой базой данных, такой как SQLite.Это может быть небольшим излишним, но, с другой стороны, реализация атомарности самостоятельно может немного изобретать колесо (и я не нашел никаких очевидных библиотек, которые бы делали это для вас).

Если вы решитечтобы пойти хитрым путем, эта тема рассматривается в главе «Синхронизация процессов» книги «Силбершац операционные системы» в разделе «атомарные транзакции».просто записывать в новый файл каждый раз, так что если кто-то испортит, у вас есть история.Вы даже можете добавить контрольную сумму в каждый файл, чтобы автоматически определить, не сломан ли он.

0 голосов
/ 24 ноября 2010

Вы спрашиваете, как реализовать базу данных, которая предоставляет ACID гарантии, но вы не предоставили вескую причину, почему вы не можете использовать одну из готовых.SQLite идеально подходит для такого рода вещей и дает вам такие гарантии.

Однако существует KirbyBase .Я никогда не использовал его и не думаю, что он дает гарантии ACID, но у него есть некоторые характеристики, которые вы ищете.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...