Comment pickle un namedtuple instance correctement
Je suis en train d'apprendre comment utiliser la saumure. J'ai créé un namedtuple objet, ajouté à une liste, et a essayé de les achards de cette liste. Cependant, j'obtiens l'erreur suivante:
pickle.PicklingError: Can't pickle <class '__main__.P'>: it's not found as __main__.P
J'ai trouvé que si j'ai couru le code sans l'enveloppant à l'intérieur d'une fonction, il fonctionne parfaitement. Est-il une étape supplémentaire nécessaire pour mariner un objet enveloppé à l'intérieur d'une fonction?
Voici mon code:
from collections import namedtuple
import pickle
def pickle_test():
P = namedtuple("P", "one two three four")
my_list = []
abe = P("abraham", "lincoln", "vampire", "hunter")
my_list.append(abe)
f = open('abe.pickle', 'w')
pickle.dump(abe, f)
f.close()
pickle_test()
- Malheureusement, pickle ne semble pas bien fonctionner avec namedtuples.
pickle
poignées namedtuple classes amende; les classes définies dans une fonction d'espace de noms local pas tellement.- double possible de Python: ne Peut pas les achards de type X, attribut de recherche a échoué
- Cette question a été posée/répondu il y a un an 🙂
- Cela n'affecte pas si c'est un doublon et maintenant, les questions sont liées les unes aux autres dans la barre latérale, ce qui est utile. Le commentaire n'est pas une critique, il est généré automatiquement lors de repérage.
- Ne vous en faites pas. J'ai juste pensé que c'était drôle. La Question des liens très utiles 🙂
- Il y a un problème similaire. Si le type de variable et le type de chaîne utilisé dans le constructeur ne sont pas les mêmes alors pickle échouera également. par exemple,
P = namedtuple("Q", "one two three four")
- Pour la postérité: cette erreur se produit également si le
typename
argument namedtuple ne correspond pas au nom de la classe retournée par namedtuple. Voir: stackoverflow.com/a/28149627/3396951
Vous devez vous connecter pour publier un commentaire.
Créer le nommé tuple à l'extérieur de la fonction:
Maintenant
pickle
pouvez le trouver; c'est un module mondial maintenant. Lorsque unpickling, tous lespickle
module de a à faire est de localiser__main__.P
de nouveau. Dans votre version,P
est un local, à lapickle_test()
fonction, et qui n'est pas introspectable ou importables.Il est important de se rappeler que
namedtuple()
est une fabrique de classe; vous donner les paramètres et retourne un objet de classe pour vous de créer des instances de.pickle
seulement les magasins de la données contenues dans les instances, en plus d'une chaîne de référence de la classe d'origine de reconstruire les instances de nouveau.namedtuple
dynamiquement parce que je ne connais pas les champs jusqu'à l'exécution? Est-il encore un moyen de contourner ce problème? J'ai essayé de créer une autre méthode en dehors de la classe, mais cela ne fonctionne pas.globals()
pour obtenir un mappage) en vertu de la même nom, etpickle
pouvez le trouver encore.Après j'ai ajouté à ma question dans un commentaire de la principale réponse que j'ai trouvé un moyen de résoudre le problème de la dynamique créée
namedtuple
cornichon-mesure. Cela est nécessaire dans mon cas parce que je suis en train de comprendre ses champs qu'à l'exécution (après un DB de la requête).Tout ce que je fais est monkey patch la
namedtuple
en le déplaçant vers la__main__
module:L'esprit que le
namedtuple
nom (qui est fourni parargs
) peut remplacer un autre membre__main__
si vous ne faites pas attention.globals()
à la place:globals()[namedtupleClass.__name__] = namedtupleClass
. Il y a ensuite pas besoin pour définir le__module__
.globals()[namedtupleClass.__name__] = namedtupleClass
il n'a, en effet, permettez-moi de pickle mon objet, mais quand j'ai essayé de unpickle elle n'a pas lanamedtupleClass
elle avait besoin. Mon conseil est de il suffit d'utiliser un dictionnaire jusqu'à ce qu'ils font pickle assez intelligents pour le faire.J'ai trouvé cette réponse dans un autre thread. Ce est tout au sujet de la désignation de l'nommé n-uplet. Cela a fonctionné pour moi:
Alternativement, vous pouvez utiliser
cloudpickle
ouaneth
pour la sérialisation:La question ici est l'enfant du processus ne sont pas en mesure d'importer la classe de l'objet -dans ce cas, la classe P-, dans le cas d'une multi-projet de modèle de la Classe P doit être importable n'importe où le processus de l'enfant de s'habituer
une rapide solution est de faire il importable en affectant à globals()