La sauvegarde d'un Objet (la persistance des Données)
J'ai créé un objet comme ceci:
company1.name = 'banana'
company1.value = 40
Je voudrais enregistrer cet objet. Comment puis-je le faire?
- Voir exemple pour les gens qui viennent ici pour un exemple simple comment utiliser la saumure.
- Pourquoi avez-vous (apparemment) préfèrent que la réponse à la accepté un (de la lié question)?
- Au moment où je me suis lié, l'on a accepté la réponse n'a pas
protocol=pickle.HIGHEST_PROTOCOL
. Ma réponse donne aussi des alternatives de jus.
Vous devez vous connecter pour publier un commentaire.
Vous pouvez utiliser le
pickle
module de la bibliothèque standard.Voici un élémentaire d'application à votre exemple:
Vous pouvez également définir votre propre utilitaire simple comme la suivante, qui ouvre un fichier et écrit un seul objet:
Mise à jour:
Puisque c'est une réponse, j'aimerais toucher un peu légèrement utilisation avancée des sujets.
cPickle
(ou_pickle
) vspickle
Il est presque toujours préférable d'utiliser effectivement le
cPickle
module plutôt quepickle
parce que le premier est écrit en C et est beaucoup plus rapide. Il ya quelques différences subtiles entre eux, mais dans la plupart des cas elles sont équivalentes et la C version grandement les performances supérieures. Commutation de il ne pouvait pas être plus facile, il suffit de changer leimport
texte de la déclaration:En Python 3,
cPickle
a été renommé_pickle
, mais cela n'est plus nécessaire puisque lapickle
module maintenant c'est fait automatiquement—voir Quelle est la différence entre un cornichon et _pickle en python 3?.La réduction est vous pouvez utiliser quelque chose comme ce qui suit pour vous assurer que votre code toujours utiliser la version C quand il est disponible en Python 2 et 3:
Flux de données formats (protocoles)
pickle
peut lire et écrire des fichiers dans plusieurs différentes, Python-spécifiques, les formats, appelé protocoles comme décrit dans la la documentation, "Protocole de la version 0" est l'ASCII et donc "lisible". Les Versions > 1 sont binaires et le plus élevé disponible dépend de la version de Python est utilisé. La valeur par défaut dépend aussi de la version de Python. En Python 2 la valeur par défaut est la version du Protocole0
, mais en Python 3.7, c'est la version du Protocole3
. En Python 3.x le module a unpickle.DEFAULT_PROTOCOL
ajouté à cela, mais qui n'existe pas en Python 2.Heureusement, il y a un raccourci pour l'écriture
pickle.HIGHEST_PROTOCOL
lors de chaque appel (en supposant que c'est ce que vous voulez, et vous le faites habituellement), il suffit d'utiliser le nombre littéral-1
— similaire à référencer le dernier élément d'une séquence par l'intermédiaire d'un indice négatif.Donc, au lieu d'écrire:
Vous pouvez simplement écrire:
De toute façon, il vous suffit de spécifier le protocole une fois, si vous avez créé un
Pickler
objet pour une utilisation dans de multiples pickle opérations:Note: Si vous êtes dans un environnement qui exécutent différentes versions de Python, alors vous aurez probablement envie d'utiliser de manière explicite (c'est à dire coder en dur) un numéro de protocole que tous peuvent lire (les versions ultérieures peuvent généralement lire les fichiers produits par les précédents).
Plusieurs Objets
Tout un cornichon fichier peut contenir n'importe quel nombre de marinés objets, comme indiqué dans les échantillons ci-dessus, quand il y a un nombre inconnu d'entre eux, il est souvent plus facile de stocker toutes dans une sorte de variable contenant de la taille, comme un
list
,tuple
, oudict
et les écrire dans le fichier en un seul appel:et de restauration de la liste et tout de suite:
L'avantage majeur est que vous n'avez pas besoin de savoir combien d'instances de l'objet sont enregistrés dans l'ordre de charger les reprendre plus tard (bien que de le faire sans que les informations est possible, elle nécessite un petit peu de code spécialisé). Voir les réponses à la question relative à la Sauvegarde et chargement de plusieurs objets dans la saumure fichier? pour plus de détails sur les différentes façons de le faire. Personnellement je comme @Lutz Prechelt de réponse le meilleur. Ici, il est adapté pour les exemples ici:
company1
etcompany2
. Pourquoi ne pas supprimer aussiCompany
et de montrer ce qui se passe?dill
module que vous avez écrit — qui a certainement sonne comme il pourrait être très utile dans certaines situations.dill
serait d'exprimer plus clairement ce qu'il peut faire quepickle
ne peuvent sur sa page de téléchargement, plutôt que de proposer son utilisation pour résoudre des problèmes sans rapport avec le problème à la main dans différents AFIN de postes. Si il y a un consensus qu'il réponde adéquatement à de graves lacunes gens sont couramment rencontrer en essayant d'utiliserpickle
, il faudrait peut-être fait partie de la bibliothèque standard.pickle
échouera vous dans la plupart des cas. Ma réponse est le plus général, donc le bon type de l'ongle. J'ai été la cueillette à une croûte un peu dans les commentaires de votre réponse, mais ça reste à mon avis un argument valable. Vous avez tout à fait le droit d'être en désaccord. ...et je ne suis pas vraiment d'essayer de promouvoir desdill
, je suis juste de répondre à la question avec tous les outils que j'ai dans ma boîte à outils.for
boucle, puis à l'intérieur de générer chaque nom de fichier. c'est à direfilename = 'myname{}.pkl'.format(count)
, suivie parcount += 1
. Toutefois, il serait probablement préférable de mettre tous les objets dans une liste etpickle.dump()
, ce qui nous permettra d'économiser à la fois dans un seul fichier et de préserver l'ordre où ils apparaissent dans la liste. Vous pouvez aussi les mettre dans un dictionnaire etdump()
que.HIGHEST_PROTOCOL
, car il est généralement va produire le plus petit (et probablement le plus rapide) des résultats.Je pense que c'est assez forte hypothèse de supposer que l'objet est un
class
. Si ce n'est pas unclass
? Il y a aussi l'hypothèse que l'objet n'est pas définie dans l'interpréteur. Que faire si il a été défini dans l'interpréteur? Aussi, si les attributs ont été ajoutés dynamiquement? Lorsque certains objets python ont des attributs ajoutés à leur__dict__
après la création,pickle
ne respecte pas l'ajout de ces attributs (c'est à dire qu'il 'oublie' ils ont été ajoutés par la suite, parce quepickle
sérialise par référence à la définition de l'objet).Dans tous ces cas,
pickle
etcPickle
peut échouer vous horriblement.Si vous cherchez à économiser un
object
(arbitrairement créé), où les attributs (soit ajouté dans la définition de l'objet, ou par la suite)... votre meilleur pari est d'utiliserdill
, qui peut sérialiser presque rien en python.Nous commençons avec une classe...
Maintenant arrêter et redémarrer...
Oups...
pickle
ne peut pas le manipuler. Essayonsdill
. Nous allons jeter un autre type d'objet (unlambda
) pour faire bonne mesure.Et maintenant lire le fichier.
Il fonctionne. La raison
pickle
échoue, etdill
ne l'est pas, c'est quedill
traite__main__
comme un module (pour la plupart), et peut également pickle définitions de classe au lieu de décapage par référence (commepickle
n'). La raisondill
pouvons pickle unlambda
est qu'il lui donne un nom... puis le décapage de la magie qui peut arriver.En fait, il y a un moyen facile d'économiser tous ces objets, surtout si vous avez beaucoup d'objets que vous avez créés. Juste dump l'ensemble de python session, et revenez-y plus tard.
Maintenant éteindre votre ordinateur, allez profiter d'un espresso ou que ce soit, et de revenir plus tard...
Le seul inconvénient majeur est que
dill
ne fait pas partie de l'python standard library. Donc, si vous ne pouvez pas installer un paquet python sur votre serveur, vous ne pouvez pas l'utiliser.Toutefois, si vous êtes en mesure d'installer les paquets python sur votre système, vous pouvez obtenir les dernières
dill
avecgit+https://github.com/uqfoundation/dill.git@master#egg=dill
. Et vous pouvez obtenir la dernière version avecpip install dill
.TypeError: __new__() takes at least 2 arguments (1 given)
lorsque vous essayez d'utiliserdill
(qui a l'air prometteur) avec un objet assez complexe qui comprend un fichier audio.TypeError
lorsque vous faites quoi, exactement? C'est habituellement un signe d'avoir le nombre d'arguments incorrect lors de l'instanciation d'une instance de classe. Si ce n'est pas une partie du flux de travail de la question ci-dessus, pourriez-vous poster une autre question, envoyez-moi par e-mail, ou d'ajouter une question sur ladill
github page?dill
question.Vous pouvez utiliser anycache pour faire le travail pour vous. Elle tient compte de tous les détails:
qui s'étend le python
pickle
module pour gérerlambda
et toutes les bellespython dispose d'.
En supposant que vous avez une fonction
myfunc
qui crée l'instance:Anycache appels
myfunc
à la première fois et les cornichons le résultat d'unefichier dans
cachedir
à l'aide d'un identifiant unique (selon le nom de la fonction et ses arguments) comme nom de fichier.Sur une période consécutive de s'exécuter, le marinés objet est chargé.
Si le
cachedir
est conservé entre python exécute, le marinés objet est pris à partir de la précédente python exécuter.Pour plus de détails voir le la documentation
anycache
à sauver plus d'un exemple de, disons, unclass
ou conteneur comme unlist
(qui n'était pas le résultat de l'appel d'une fonction)?