web-dev-qa-db-fra.com

Décompresser un objet python 2 avec python 3

Je me demande s’il est possible de charger un objet qui a été décapé dans Python 2.4, avec Python 3.4.

J'ai utilisé 2to3 sur une grande quantité de code hérité de la société 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 examinant l'objet en conflit, il s'agit d'une dict dans un 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 décapé dans python 2.4, avec python 3.4?

109
NDevox

Vous devrez indiquer à pickle.load() comment convertir Python les données de bytest en Python 3 chaînes, ou vous pouvez indiquer à pickle de les conserver sous forme d'octets.

La valeur par défaut consiste à essayer de décoder toutes les données de chaîne au format ASCII. Ce décodage échoue. Voir la documentation pickle.load()) :

Les arguments de mot clé facultatifs sont fix_imports , codant et erreurs , utilisées pour contrôler la compatibilité du flux de pickles généré par Python 2. Si fix_imports est vrai, cornichon essaiera de mapper les anciens noms Python 2 aux nouveaux noms utilisés dans Python 3. Le codage et des erreurs indiquent à pickle comment décoder des instances de chaînes de 8 bits sélectionnées par Python 2; Ces valeurs sont définies par défaut sur "ASCII" et "strict". Le codage peut être un "octet" pour lire ces occurrences de chaînes de 8 bits sous forme d’objets octets.

Définir le codage sur latin1 vous permet d'importer directement les données:

with open(mshelffile, 'rb') as f:
    d = pickle.load(f, encoding='latin1') 

mais vous devrez vérifier qu'aucune de vos chaînes n'est décodée à l'aide du mauvais codec; Latin-1 fonctionne pour toute 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 les clés et valeurs bytes par la suite.

Notez que jusqu’à Python versions antérieures à 3.6.8, 3.7.2 et 3.8.0, le dépickage de Python 2 datetime les données de l’objet sont rompues = sauf si vous utilisez encoding='bytes'.

167
Martijn Pieters

L'utilisation de encoding = 'latin1' provoque certains problèmes lorsque votre objet contient des tableaux numpy.

Utiliser encoding = bytes sera mieux.

Veuillez voir ceci réponse pour une explication complète sur l’utilisation de encoding = bytes

11
Sreeragh A R