2014-04-03 6 views
5

I-Daten von 2,7 gebeizt habe, dass ich so gebeizt:Unpickling Daten von Python 2 mit Unicode-Strings in Python 3

#!/usr/bin/env python2 
# coding=utf-8 

import pickle 

data = {1: datetime.date(2014, 3, 18), 
     'string-key': u'ünicode-string'} 

pickle.dump(data, open('file.pickle', 'wb')) 

Der einzige Weg, ich 3.4 dies in Python laden gefunden ist:

data = pickle.load(open('file.pickle', "rb"), encoding='bytes') 

Jetzt meine Unicode-Zeichenfolge sind in Ordnung, aber die dict-Tasten sind bytes. print(repr(data)) gibt:

{1: datetime.date(2014, 3, 18), b'string-key': 'ünicode-string'} 

jemand eine Idee Hat meinen Code wie data[b'string-key'] bzw. zu umgehen, neu zu schreiben. alle vorhandenen Dateien konvertieren?

+0

Eingelegte Daten werden nicht über Versionen und Implementierungen hinweg funktionieren und sind eine ziemlich schlechte Serialisierungsmethode, die auch dann verwendet wird, wenn sie überhaupt funktioniert, weil sie willkürlichen Code ausführt. Haben Sie darüber nachgedacht, stattdessen JSON zu verwenden? – geoffspear

+0

Ich habe eine komplexere Struktur, die Dicts, Tupel und Tupel von Tupeln als Werte enthält, und ich muss Versionen der gespeicherten Daten vergleichen, und zu diesem Zweck sind Tupel viel bequemer als Listen. Aber es gibt keine Tupel in JSON (und denke auch keine Daten?). – TNT

+0

@Wooble: [aber im Allgemeinen sollte Pickle immer der bevorzugte Weg sein, um Python-Objekte zu serialisieren] (https://docs.python.org/3/library/pickle.html#comparison-with-marshal) –

Antwort

0

Werfen Sie einen Blick auf die Implementierung.

Sie können unterklassifizieren und die Byte-Deserialisierung überschreiben, um Strings zu erzeugen.

4

Dies ist keine echte Antwort, sondern nur ein Workaround. Dieser wandelt in Essig eingelegten Daten auf Version 3 in Python 3.4 (funktioniert nicht in 3.3):

#!/usr/bin/env python3 

import pickle, glob 

def bytes_to_unicode(ob): 
    t = type(ob) 
    if t in (list, tuple): 
     l = [str(i, 'utf-8') if type(i) is bytes else i for i in ob] 
     l = [bytes_to_unicode(i) if type(i) in (list, tuple, dict) else i for i in l] 
     ro = tuple(l) if t is tuple else l 
    elif t is dict: 
     byte_keys = [i for i in ob if type(i) is bytes] 
     for bk in byte_keys: 
      v = ob[bk] 
      del(ob[bk]) 
      ob[str(bk,'utf-8')] = v 
     for k in ob: 
      if type(ob[k]) is bytes: 
       ob[k] = str(ob[k], 'utf-8') 
      elif type(ob[k]) in (list, tuple, dict): 
       ob[k] = bytes_to_unicode(ob[k]) 
     ro = ob 
    else: 
     ro = ob 
     print("unprocessed object: {0} {1}".format(t, ob)) 
    return ro 

for fn in glob.glob('*.pickle'): 

    data = pickle.load(open(fn, "rb"), encoding='bytes') 
    ndata = bytes_to_unicode(data) 
    pickle.dump(ndata, open(fn + '3', "wb")) 

Die Python docs sagen:

Die Gurke Serialisierungsformat ist garantiert rückwärts kompatibel sein über Python veröffentlicht.

ich einen Weg zu pickle.load Python-2.7 eingelegten Daten in Python 3.3 nicht finden - nicht einmal Daten, die nur int s und date s enthalten.

+0

Sie sollten einen Fehler (falls noch nicht vorhanden) auf dem [Python Bug Tracker] (http://bugs.python.org) öffnen. –