2009-10-31 3 views
0

Quelle serait la meilleure façon de gérer la récupération après sinistre légère pour mon programme?Récupération après incident légère pour Python

J'ai un programme Python qui exécute un certain nombre de cas de test et les résultats sont stockés dans un dictionnaire qui sert de cache. Si je pouvais enregistrer (puis restaurer) chaque élément ajouté au dictionnaire, je pourrais simplement exécuter à nouveau le programme et la mise en cache fournirait une récupération de panne appropriée.

  1. Vous pouvez supposer que les clés et les valeurs dans le dictionnaire sont facilement convertibles en chaînes de caractères. en utilisant soit str ou le pickle module.
  2. Je veux que ce soit complètement plate-forme - bien au moins en tant que plateforme croisée que Python est
  3. Je ne veux pas simplement écrire chaque valeur à un fichier et le charger dans mon programme pourrait se bloquer pendant que j'écris le fichier
  4. MISE À JOUR: Ceci est destiné à être un module léger, donc un SGBD est hors de question.
  5. MISE À JOUR: Alex est correct que je ne suis pas réellement besoin pour protéger contre les accidents lors de l'écriture, mais il y a des circonstances où je voudrais être en mesure de mettre fin à la main dans un état récupérable.
  6. MISE À JOUR Ajout d'une solution très limitée en utilisant l'entrée standard ci-dessous

Répondre

2

Il n'y a pas de bonne façon pour se prémunir contre "votre programme s'écraser tandis que écrire un point de contrôle dans un fichier", mais pourquoi devriez-vous vous soucier autant de que?! Qu'est-ce que votre programme fait à ce moment-là, en plus de "sauvegarder le point de contrôle dans un fichier", ce qui pourrait facilement provoquer un crash?!

Il est difficile de battre pickle (ou cPickle) pour la portabilité de la sérialisation en Python, mais il s'agit simplement de «transformer vos clés et valeurs en chaînes». Pour enregistrer des paires clé-valeur (une fois stringifiées), quelques approches sont plus sûres que l'ajout à un fichier (ne pas pickle aux fichiers si vos plantages sont loin, beaucoup plus fréquents que la normale, comme vous le suggérez).

Si votre environnement est incroyablement accidentogènes pour une raison quelconque (très pas cher HW -), assurez-vous que vous fermez le fichier (et fflush si le système d'exploitation est également accidentogènes ;-), puis rouvrez pour ajouter. De cette façon, le pire qui puisse arriver est que le tout dernier ajout sera incomplet (à cause d'un crash au milieu des choses) - alors vous attrapez juste l'exception déclenchée en défaisant ce disque incomplet et refaites seulement les choses qui n'étaient pas sauvé (parce qu'ils n'ont pas été terminés en raison d'un accident, OU parce qu'ils ont été achevés mais pas entièrement sauvés en raison d'un accident, arrive à peu près la même chose à la fin).

Si vous avez la possibilité de pointer vers un moteur de base de données (au lieu de simplement le faire dans des fichiers), considérez-le sérieusement! Le moteur DB conservera les journaux de transactions et assurera les propriétés ACID, ce qui rendra la programmation de votre application beaucoup plus facile SI vous pouvez compter dessus!-)

+0

Vous avez raison de dire qu'il n'y a aucune raison pour que mon programme plante lors de l'écriture de données dans un fichier et que la protection soit probablement paranoïaque. Cependant, il y a parfois des circonstances où il serait pratique pour moi de terminer manuellement le programme et de le récupérer. – Casebash

+0

Casebash: Ne devriez-vous pas piéger le signal d'interruption tout en effectuant des opérations sensibles? –

+0

Bon point. Je peux alors le régler pour terminer dès que l'opération sensible est terminée – Casebash

1

Le module pickle prend en charge les objets sérialisation dans un fichier (et le chargement du fichier):

http://docs.python.org/library/pickle.html

+0

Merci de signaler. J'ai déjà utilisé ce module, mais j'ai oublié de le mentionner dans ma réponse. – Casebash

1

Une possibilité serait de créer un certain nombre de fichiers plus petits ... chacun représentant un sous-ensemble de l'état que vous essayez de préserver et chacun avec une somme de contrôle ou une étiquette indiquant qu'il est complet comme dernière ligne/datum du fichier (juste avant la fermeture du fichier). Si le checksum/tag est bon, alors le reste des données peut être considéré valide ... bien que le programme devrait alors trouver tous ces fichiers, les ouvrir et les lire tous, et utiliser les méta-données que vous avez fourni (dans leurs en-têtes ou leurs noms?) pour déterminer lesquels constituent la représentation d'état cohérente la plus récente (ou point de contrôle) à partir de laquelle vous pouvez continuer le traitement.

Sans en savoir plus sur la nature des données avec lesquelles vous travaillez, il est impossible d'être plus précis.

Vous pouvez utiliser des fichiers, bien sûr, ou vous pouvez utiliser un système SGBD à peu près aussi facilement. Tout SGBD décent (PostgreSQL, MySQL si vous utilisez les back-ends de stockage appropriés) peut vous donner des garanties ACID et un support transactionnel. Ainsi, les données que vous lisez doivent toujours être cohérentes avec les contraintes que vous mettez dans votre schéma et/ou avec les transactions (BEGIN, COMMIT, ROLLBACK) que vous avez traitées. Un avantage possible de la publication de votre date sérialisée sur un SGBD est que vous pouvez héberger le SGBD sur un système distinct (qui ne souffrira probablement pas des mêmes instabilités que votre hôte de test au même moment).

+0

J'aurais dû mentionner dans la question initiale qu'un SGBD était hors de question – Casebash

+0

Checksumming fonctionnera la plupart du temps, mais pourrait échouer si la fin du fichier après un accident vient d'être une somme de contrôle correspondant.Bien sûr, c'est assez rare – Casebash

+0

Si vous fermez immédiatement après avoir écrit la somme de contrôle (rappelez-vous que vous ouvrez de nouveaux fichiers pour les nouveaux "paquets" de point de contrôle) ... puis les chances d'un crash qui cherche dans notre fichier, le corrompt, et le fait avec un motif qui arrive juste à correspondre à votre checksum, sans corrompre * il * semble être arbitrairement petit --- même pour un hachage CRC32 trivial). –

1

Pickle/cPickle ont des problèmes. J'utilise le module JSON pour sérialiser des objets. Je l'aime parce que non seulement cela fonctionne sur n'importe quel système d'exploitation, mais il fonctionnera bien dans d'autres langages de programmation, aussi; De nombreux autres langages et plates-formes ont une prise en charge de la désérialisation JSON facilement accessible, ce qui facilite l'utilisation des mêmes objets dans différents programmes.

+1

J'ai entendu dire que JSON est plus agréable à lire, ce qui peut permettre une récupération manuelle après un crash – Casebash

0

Solution avec des restrictions sévères

Si je ne vous inquiétez pas écraser tout en écrivant dehors et je veux seulement pour permettre la résiliation manuelle, je peux utiliser la sortie standard pour contrôler cela. Malheureusement, ceci peut seulement terminer le programme quand un point de contrôle est atteint. Cela pourrait être résolu en créant un nouveau thread pour lire l'entrée standard. Ce thread pourrait utiliser un verrou global pour vérifier si le thread principal est dans une section critique (écrire dans un fichier) et terminer le programme si ce n'est pas le cas.

: Downsides

  • Ce complexe est raisonnablement
  • Il ajoute un fil supplémentaire
  • Il me arrête d'utiliser l'entrée standard pour toute autre chose
Questions connexes