【问题标题】:msgpack unserialising dict key strings to bytesmsgpack 将 dict 键字符串反序列化为字节
【发布时间】:2018-06-27 10:42:28
【问题描述】:

我在 python 中遇到了msgpack 的问题。似乎在序列化dict 时,如果键是字符串str,则它们没有正确反序列化并导致引发KeyError 异常。

例子:

>>> import msgpack
>>> d = dict()
>>> value = 1234
>>> d['key'] = value
>>> binary = msgpack.dumps(d)
>>> new_d = msgpack.loads(binary)
>>> new_d['key']
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
KeyError: 'key'

这是因为在调用 loads() 后键不是字符串,而是反序列化为 bytes 对象。

>>> d.keys()
dict_keys(['key'])
>>> new_d.keys()
dict_keys([b'key'])

这似乎与in github提到的一个未实现的功能有关

我的问题是,有没有办法解决这个问题或解决方法以确保在反序列化时可以使用相同的密钥?

我想使用msgpack,但如果我无法使用str 键构建dict 对象并希望能够在反序列化时使用相同的键,它就变得无用了。

【问题讨论】:

  • 另见github.com/msgpack/msgpack/issues/121#issuecomment-13815058 我建议您将all 字符串编码为UTF-8,然后再将它们传递给msgpack,然后在解包时解码。这样做还可以防止 ASCII / Latin1 范围之外的 Unicode 被破坏。
  • 谢谢!这是问题,但来源与msgpack 的编码问题有关。你帮助追查了问题。回答跟随。

标签: python msgpack


【解决方案1】:

尝试以下方法:

def c_msgpackloads(bin):
    new_d = msgpack.loads(bin)
    new_d = {key.decode('utf-8') if isinstance(key, bytes) else key: new_d[key].decode('utf-8') if isinstance(new_d[key], bytes) else new_d[key] for key in new_d}
    return new_d

这是一个自定义加载函数,加载dict并自动将bytes键和值编码为utf-8字符串。

【讨论】:

  • 谢谢,佩德罗。不错的技巧,但这只是一个编码问题。将发布答案。
【解决方案2】:

调用dumpspackb时设置默认编码

:param str encoding:
 |      Convert unicode to bytes with this encoding. (default: 'utf-8')

但在调用loadsunpackb 时默认设置为,如下所示:

Help on built-in function unpackb in module msgpack._unpacker:

unpackb(...)
    unpackb(... encoding=None, ... )

因此更改反序列化的编码可以解决问题,例如:

>>> d['key'] = 1234
>>> binary = msgpack.dumps(d)
>>> msgpack.loads(binary, encoding = "utf-8")
{'key': 1234}
>>> msgpack.loads(binary, encoding = "utf-8") == d
True

【讨论】:

  • 编码已被弃用 -- raw=True|False 是新方法。
【解决方案3】:

在您的示例中使用 raw=False 标志对我有用:

msgpack.unpackb(binary, raw=False)
# or
msgpack.loads(binary, raw=False)

https://msgpack-python.readthedocs.io/en/latest/api.html#msgpack.Unpacker:

raw (bool) -- 如果为 true,则将 msgpack raw 解压缩为 Python 字节。否则,通过使用 UTF-8 编码(默认)解码来解压到 Python str。

【讨论】:

    猜你喜欢
    • 2021-01-08
    • 2020-05-20
    • 2012-08-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-08-16
    相关资源
    最近更新 更多