Je me demande s'il existe un moyen de charger un objet qui a été picklé dans Python 2.4, avec Python 3.4.
J'ai utilisé 2to3 sur une grande quantité de code hérité de l'entreprise pour le mettre à jour.
Après avoir fait cela, lors de l'exécution du fichier, j'obtiens l'erreur suivante:
File "H:\fixers - 3.4\addressfixer - 3.4\trunk\lib\address\address_generic.py"
, line 382, in read_ref_files
d = pickle.load(open(mshelffile, 'rb'))
UnicodeDecodeError: 'ascii' codec can't decode byte 0xe2 in position 1: ordinal
not in range(128)
En regardant l'objet mariné en conflit, c'est un dict
dans a dict
, contenant des clés et des valeurs de type str
.
Ma question est donc la suivante: existe-t-il un moyen de charger un objet, initialement picklé en python 2.4, avec python 3.4?
json
module? Vous pourriez peut-être écrire un script 2.4 qui décoche l'objet et l'enregistre en tant qu'objet json, puis écrire un script 3.4 qui lit l'objet json et l'enregistre en tant qu'objet pickle compatible 3.4. Ce serait une opération unique que vous exécutez sur tous vos fichiers pickle.Réponses:
Vous devrez dire
pickle.load()
comment convertir les données Python bytestring en chaînes Python 3, ou vous pouvez direpickle
de les laisser sous forme d'octets.La valeur par défaut est d'essayer de décoder toutes les données de chaîne au format ASCII, et ce décodage échoue. Consultez la
pickle.load()
documentation :Le paramétrage du codage sur
latin1
vous permet d'importer directement les données:mais vous devrez vérifier qu'aucune de vos chaînes n'est décodée en utilisant le mauvais codec; Latin-1 fonctionne pour n'importe quelle entrée car il mappe directement les valeurs d'octet 0-255 aux 256 premiers points de code Unicode.
L'alternative serait de charger les données avec
encoding='bytes'
et de décoder toutes lesbytes
clés et valeurs par la suite.Notez que jusqu'aux versions Python antérieures à 3.6.8, 3.7.2 et 3.8.0, le décolmatage des
datetime
données d'objet Python 2 est interrompu sauf si vous utilisezencoding='bytes'
.la source
encoding
complètement le mot clé pour Python 2.'encoding': 'latin1'
et envoie ** pickle_options à pickle. De cette façon, il devrait fonctionner dans les deux versions.datetime
commentaire n'était pas l'objectif principal de cette réponse, mais pour les futurs lecteurs, j'aimerais souligner que même les versions "fixes" de Python 3 nécessitent encoreencoding='latin-1'
de décocher les datetimes Python 2. Si vos données Python 2 marinées incluent à la fois des datetimes et des chaînes d'octets encodés dans autre chose que Latin-1, alors vous feriez peut-être encore mieux d'utiliserencoding='bytes'
après tout.L'utilisation
encoding='latin1'
provoque certains problèmes lorsque votre objet contient des tableaux numpy.L'utilisation
encoding='bytes'
sera meilleure.Veuillez consulter cette réponse pour une explication complète de l'utilisation
encoding='bytes'
la source
bytes
transforme les chaînes en bytes (), donc je préfèrelatin1
si possible, mais je ne sais pas quel est le problème.numpy.ndarray
(numpy 1.14) mariné dans Python 2.7 en utilisantcPickle.dumps()
, et unpickling dans Python 3 avecpickle.loads(..., encoding='latin1')
fonctionne bien.