Ich frage mich, ob es eine Möglichkeit gibt, ein in Python 2.4 eingelegtes Objekt mit Python 3.4 zu laden.
Ich habe 2to3 mit einer großen Menge von Firmen-Legacy-Code ausgeführt, um ihn auf den neuesten Stand zu bringen.
Nachdem ich dies getan habe, erhalte ich beim Ausführen der Datei den folgenden Fehler:
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)
Wenn Sie das in Konflikt stehende eingelegte Objekt betrachten, ist es ein dict
in a dict
, das Schlüssel und Werte vom Typ enthält str
.
Meine Frage lautet also: Gibt es eine Möglichkeit, ein ursprünglich in Python 2.4 eingelegtes Objekt mit Python 3.4 zu laden?
json
Modul? Vielleicht könnten Sie ein 2.4-Skript schreiben, das das Objekt entpickt und als JSON-Objekt speichert, und dann ein 3.4-Skript schreiben, das das JSON-Objekt liest und es als 3.4-kompatibles Pickle-Objekt speichert. Dies wäre eine einmalige Operation, die Sie für alle Ihre Pickle-Dateien ausführen.Antworten:
Sie müssen
pickle.load()
angeben , wie Python-Bytestring-Daten in Python 3-Zeichenfolgen konvertiert werden sollen, oder Sie können festlegenpickle
, dass sie als Bytes belassen werden sollen .Standardmäßig wird versucht, alle Zeichenfolgendaten als ASCII zu dekodieren. Diese Dekodierung schlägt fehl. Siehe die
pickle.load()
Dokumentation :Wenn Sie die Codierung auf einstellen,
latin1
können Sie die Daten direkt importieren:Sie müssen jedoch überprüfen, ob keine Ihrer Zeichenfolgen mit dem falschen Codec dekodiert wurde. Latin-1 funktioniert für jede Eingabe, da die Bytewerte 0-255 direkt den ersten 256 Unicode-Codepunkten zugeordnet werden.
Die Alternative wäre, die Daten mit zu laden
encoding='bytes'
und anschließend allebytes
Schlüssel und Werte zu dekodieren .Beachten Sie, dass bis zu Python-Versionen vor 3.6.8, 3.7.2 und 3.8.0 das Aufheben der Auswahl von Python 2-
datetime
Objektdaten unterbrochen ist, sofern Sie diese nicht verwendenencoding='bytes'
.quelle
encoding
Schlüsselwort für Python 2.'encoding': 'latin1'
** pickle_options hat und an pickle sendet. Auf diese Weise sollte es in beiden Versionen ausgeführt werden.datetime
Kommentar nicht der Hauptschwerpunkt dieser Antwort war, aber für zukünftige Leser möchte ich darauf hinweisen, dass selbst die "festen" Versionen von Python 3 noch dieencoding='latin-1'
Auswahl von Python 2-Datenzeiten aufheben müssen. Wenn Ihre eingelegten Python 2-Daten sowohl Datenzeiten als auch Bytestrings enthalten, die in etwas anderem als Latin-1 codiert sind, ist es möglicherweise immer noch besser, sie zu verwendenencoding='bytes'
.Die Verwendung
encoding='latin1'
verursacht einige Probleme, wenn Ihr Objekt numpy Arrays enthält.Verwenden
encoding='bytes'
wird besser sein.In dieser Antwort finden Sie eine vollständige Erklärung der Verwendung
encoding='bytes'
quelle
bytes
macht Strings zu Bytes (), daher bevorzuge ich es,latin1
wenn möglich, aber mir ist nicht klar, wo das Problem liegt.numpy.ndarray
(numpy 1.14) in Python 2.7 mit eingelegtcPickle.dumps()
, und das Entfernen in Python 3 mitpickle.loads(..., encoding='latin1')
funktioniert gut.