使用Python 3中的unicode字符串从Python 2中取消数据

TNT*_*TNT 5 python-2.7 python-unicode python-3.4

我从2.7那里腌制数据,我这样腌制:

#!/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'))
Run Code Online (Sandbox Code Playgroud)

我发现在Python 3.4中加载它的唯一方法是:

data = pickle.load(open('file.pickle', "rb"), encoding='bytes')
Run Code Online (Sandbox Code Playgroud)

现在我的unicode字符串很好,但是dict键是bytes.print(repr(data))得到:

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

有没有人有想法重写我的代码,如data[b'string-key']resp.转换所有现有文件?

TNT*_*TNT 5

这不是真正的答案,而只是一种解决方法。这会将腌制数据转换为 Python 3.4 中的版本 3(在 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"))
Run Code Online (Sandbox Code Playgroud)

Python文档说:

pickle 序列化格式保证在 Python 版本之间向后兼容。

我没有pickle.load在 Python 3.3 中找到Python-2.7 腌制数据的方法——甚至没有找到只包含ints 和dates 的数据。


Use*_*ser 0

看看实施情况。

您可以子类化Unpickler并覆盖字节反序列化以生成字符串。