Domanda

Ho uno script Python (2.7) che agisce come un server e sarà quindi eseguito per lunghi periodi di tempo. Questo script ha un sacco di valori per tenere traccia di che può cambiare in qualsiasi momento, in base all'input del cliente.

Quello che sto idealmente dopo è qualcosa che può mantenere una struttura di dati Python (con valori di tipo dict, list, unicode, int e float - JSON, in fondo) in memoria, lasciando che mi aggiorno però voglio (ad eccezione di riferimento una delle istanze del tipo di riferimento più di una volta) pur mantenendo questi dati up-to-date in un file leggibile, in modo che, anche se la spina di alimentazione è stato tirato, il server potrebbe semplicemente avviare e continuare con gli stessi dati.

So che sto fondamentalmente parlando di una banca dati, ma i dati mi tengo sarà molto semplice e probabilmente meno di 1 kB maggior parte del tempo, quindi sto cercando la soluzione più semplice possibile, in grado di fornirmi con l'integrità dei dati descritto. Ci sono ogni buon Python (2.7) librerie che mi permetta di fare qualcosa di simile?

È stato utile?

Soluzione

Sono d'accordo che non hai bisogno di un database completamente bruciato, come sembra che tutto quello che vuoi è il file atomica scrive . È necessario risolvere questo problema in due parti, la serializzazione / deserialisation, e la scrittura atomica.

Per la prima sezione, json, o pickle sono probabilmente formati adatti per voi. JSON ha il vantaggio di essere leggibile. Non sembra come se questo il problema principale che si trovano ad affrontare però.

Una volta che avete serializzato l'oggetto in una stringa, utilizzare la seguente procedura per scrivere un file su disco atomicamente, ipotizzando un solo scrittore concomitante (almeno su POSIX, vedi sotto):

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)

Mentre os.rename è sovrascriverà un file esistente ed è atomica su POSIX, questo non è purtroppo il caso su Windows. Su Windows, v'è la possibilità che os.unlink riuscirà ma os.rename fallirà, il che significa che hai solo backup_filename e non filename. Se si prendono di mira Windows, è necessario prendere in considerazione questa possibilità quando si verifica l'esistenza di filename.

Se c'è una possibilità di più di uno scrittore concorrente, si dovrà prendere in considerazione un costrutto di sincronizzazione.

Altri suggerimenti

Bene, poiché si sa che stiamo fondamentalmente parlando di una base di dati, anche se molto semplice, che probabilmente non sarà sorpreso dal fatto che vi consiglio di dare un'occhiata al sqlite3 modulo.

Qual è il motivo per il requisito leggibile?

Vorrei suggerire guardando SQLite per una soluzione semplice database, o in salamoia per un modo semplice per gli oggetti deserializzare e scrivere su disco. Nessuno dei due è però leggibile soprattutto umana.

Altre opzioni sono JSON o XML, come si è accennato alla - utilizzare il costruito nel modulo di JSON per serializzare gli oggetti poi scrivono che su disco. Quando si avvia, verifica la presenza di quel file e caricare i dati, se necessario.

docs :

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

Dal momento che lei ha citato i dati è piccolo, mi piacerebbe andare con una soluzione semplice e utilizzare il salamoia modulo, che consente il dump di un oggetto Python in una linea di molto facilmente .

Poi basta impostare un Discussione che salva il vostro oggetto in un file in definito intervalli di tempo.

Non un "libraried" soluzione, ma - se ho capito le vostre esigenze -. Abbastanza semplice per voi non si ha realmente bisogno

EDIT: lei ha detto che si voleva coprire il caso che si verifica un problema durante la scrittura in sé, in modo efficace il che rende una transazione atomica. In questo caso, il modo tradizionale per andare sta usando "recupero Log-based". E 'essenzialmente scrivendo un record ad un file di log dicendo che "operazione di scrittura ha iniziato" e poi la scrittura "operazione di scrittura ha commesso" quando hai finito. Se un "iniziato" non ha alcun corrispondente "commit", allora si rollback.

In questo caso, sono d'accordo che si potrebbe essere meglio con un semplice database come SQLite. Potrebbe essere una leggera eccessivo, ma d'altra parte, l'implementazione atomicità te potrebbe essere reinventare la ruota un po '(e non ho trovato le librerie evidenti che fanno per voi).

Se si decide di andare via furbo, questo argomento è trattato sul capitolo processo di sincronizzazione del libro di sistemi operativi Silberschatz, sotto la sezione "transazioni atomiche".

Una molto semplice (anche se forse non "transazionale perfetta") alternativa sarebbe solo per registrare un nuovo file ogni volta, in modo che se uno corrompe avete una storia. È anche possibile aggiungere un checksum per ogni file per automaticamente determinare se si è rotto.

ti stai chiedendo come implementare un database che fornisce ACID garanzie, ma non ha fornito una buona ragione per cui non è possibile utilizzare un off-the-shelf. SQLite è perfetto per questo genere di cose e ti dà queste garanzie.

Tuttavia, v'è KirbyBase . Non ho mai usato e non credo che rende garanzie ACID, ma ha alcune caratteristiche che state cercando.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top