2014-04-03 15 views
5

Mam marynowanych danych od 2,7 że marynowanych tak:Unpickling dane z Pythonie 2 z ciągów Unicode w Pythonie 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')) 

Jedynym sposobem znalazłem załadować to w Pythonie 3.4 jest:

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

Teraz mój ciąg znaków unicode jest w porządku, ale klucze dyktafonu są bytes. print(repr(data)) daje:

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

Czy ktoś ma pomysł, aby ominąć przepisywanie mój kod jak data[b'string-key'] wzgl. konwersja wszystkich istniejących plików?

+0

Kiszone dane nie powinny działać w różnych wersjach i implementacjach i jest to dość zła metoda serializacji, nawet jeśli działa w ogóle, ponieważ wykonuje dowolny kod. Czy rozważałeś zamiast tego używać JSON? – geoffspear

+0

Mam bardziej złożoną strukturę, która zawiera dykta, krotki i krotki krotek jako wartości i muszę porównać wersje zapisanych danych iw tym celu krotki są znacznie bardziej wygodne niż listy. Ale w JSON nie ma krotek (i myślisz też o żadnych datach?). – TNT

+0

@Wooble: [ale ogólnie rzecz biorąc pikle powinny być zawsze preferowanym sposobem przekształcania do postaci szeregowej obiektów Pythona] (https://docs.python.org/3/library/pickle.html#comparison-with-marshal) –

Odpowiedz

0

Obejrzyj wdrożenie.

Można podklasować Unpickler i zastąpić deserializację bajtów, aby utworzyć ciągi.

4

To nie jest prawdziwa odpowiedź, ale tylko obejście tego problemu. To konwertuje dane ogórki do wersji 3 w Pythonie 3.4 (nie działa w 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")) 

Python docs powiedzieć: Format serializacji

zalewy jest gwarancją wstecznie kompatybilne całej Python zwalnia.

Nie mogę znaleźć drogę do pickle.load Pythona 2.7 marynowanych danych w Pythonie 3.3 - nawet dane, które zawierały jedynie int s i date s.

+0

Powinieneś otworzyć błąd (jeśli jeszcze nie istnieje) na [Python bug tracker] (http://bugs.python.org). –

Powiązane problemy