Mantener los datos en memoria en sincronización con un archivo para ejecutar larga secuencia de comandos de Python

StackOverflow https://stackoverflow.com/questions/4262403

Pregunta

Tengo un script de Python (2.7) que actúa como un servidor y por lo tanto tendrá una duración de períodos muy largos de tiempo. Este script tiene un montón de valores para realizar un seguimiento de lo que puede cambiar en cualquier momento sobre la base de entrada del cliente.

Lo que estoy idealmente después es algo que puede mantener una estructura de datos de Python (con valores de tipos dict, list, unicode, int y float - JSON, básicamente) en la memoria, dejando a actualizar que como quiera (excepto las referencias cualquiera de las instancias de tipo de referencia más de una vez) al mismo tiempo mantener estos datos hasta a la fecha en un archivo legible por humanos, por lo que incluso si el cable de alimentación fue retirado, el servidor podría simplemente arrancar y continuar con los mismos datos.

Sé que básicamente estoy hablando de una base de datos, pero los datos que estoy manteniendo a ser muy simple y probablemente menos de 1 kB mayor parte del tiempo, por lo que estoy buscando la solución más simple posible que me pueda proporcionar con la integridad de los datos descrito. ¿Hay buenas Python (2.7) bibliotecas que me permiten hacer algo como esto?

¿Fue útil?

Solución

Me acuerdo en que no es necesario una base de datos totalmente quemado, como parece que lo que quieres es archivo atómica escribe . Que necesita para resolver este problema en dos partes, la serialización / deserialización, y la escritura atómica.

En la primera sección, json o pickle son probablemente formatos adecuados para usted. JSON tiene la ventaja de ser legible por humanos. No parece como si esta el problema principal con el que se enfrentan sin embargo.

Una vez que haya serializado su objeto en una cadena, utilizar el siguiente procedimiento para escribir un archivo en el disco de forma atómica, asumiendo un solo escritor concurrente (al menos en POSIX, véase más adelante):

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)

Si bien es os.rename sobrescribirá un archivo existente y es atómica en POSIX, esto no es tristemente el caso en Windows. En Windows, existe la posibilidad de que os.unlink tendrá éxito, pero os.rename fallará, lo que significa que sólo tiene backup_filename y sin filename. Si el idioma de Windows, tendrá que considerar esta posibilidad cuando se está comprobando la existencia de filename.

Si hay una posibilidad de más de un escritor concurrente, se tendrá que considerar una construcción de sincronización.

Otros consejos

Bueno, ya que sabe que estamos básicamente hablando de una base de datos, aunque muy simple, es probable que no se sorprendió de que yo sugeriría que echar un vistazo a la sqlite3 módulo.

Cualquier razón de la exigencia legible por humanos?

Yo sugeriría mirar a SQLite para una solución de base de datos simple, o en salmuera para una forma sencilla de eliminar la serialización de objetos y escribir en el disco. Tampoco es legible, aunque sobre todo humano.

Otras opciones son JSON o XML a medida que insinuaste - utiliza el incorporado en el módulo json para serializar los objetos a continuación, escriben que en el disco. Al arrancar, la verificación de la presencia de ese archivo y cargar los datos si es necesario.

Desde el docs :

>>> import json
>>> print json.dumps({'4': 5, '6': 7}, sort_keys=True, indent=4)
{
    "4": 5,
    "6": 7
}

Ya que menciona sus datos es pequeña, me gustaría ir con una solución simple y uso el salmuera módulo, que le permite volcar un objeto de Python en una línea de muy fácilmente.

A continuación, sólo estableció un hilo que guarda el objeto en un archivo en definida intervalos de tiempo.

No es un "libraried" solución, pero - si entiendo sus necesidades -. Bastante simple que no necesita realmente

EDIT: usted ha mencionado que quería para cubrir el caso de que se produce un problema durante la propia escritura, haciendo efectivamente una transacción atómica. En este caso, la forma tradicional de ir es el uso de "recuperación basado en el registro". Se está escribiendo esencialmente un registro a un archivo de registro que dice que "la transacción de escritura comenzó" y luego escribir "transacción de escritura comitted" cuando haya terminado. Si un "iniciado" no tiene la correspondiente "cometer", entonces reversión.

En este caso, estoy de acuerdo que podría ser mejor con una base de datos simple como SQLite. Podría ser una ligera exageración, pero, por otro lado, la implementación de la atomicidad mismo podrían reinventar la rueda un poco (y no he encontrado ninguna biblioteca obvias que lo haga por usted).

Si decide seguir el camino astuto, este tema se trata en el capítulo Proceso de sincronización del libro de los sistemas operativos de Silberschatz, en la sección "transacciones atómicas".

Una muy simple (aunque tal vez no "transaccionalmente perfecta") alternativo fuera de registro a un nuevo archivo cada vez, de modo que si uno corrompe tiene antecedentes. Incluso se puede añadir una suma de comprobación para cada archivo de forma automática a determinar si se ha roto.

Usted está pidiendo cómo implementar una base de datos que proporciona garantías ACID , pero que no tiene proporcionado una razón buena razón por la que no se puede utilizar uno off-the-shelf. SQLite es perfecto para este tipo de cosas y le da esas garantías.

Sin embargo, no es KirbyBase . Nunca he utilizado y no creo que hace ACID garantías, pero tiene algunas de las características que usted está buscando.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top