MessagePack 是一种高效的二进制序列化格式。 它允许你在多种语言之间交换数据,就像 JSON 一样。 但它更快、更小。 这个包提供了用于读写 MessagePack 数据的 CPython 绑定。
$ pip install msgpack
msgpack 中的扩展模块(msgpack._cmsgpack)不支持 PyPy。
但是 msgpack 为 PyPy 提供了纯 Python 实现(msgpack.fallback)。
如果你无法使用官方二进制发行版,你需要在 Windows 上安装 Visual Studio 或 Windows SDK。 没有扩展,CPython 上的纯 Python 实现运行缓慢。
使用 packb 进行打包,使用 unpackb 进行解包。
msgpack 提供了 dumps 和 loads 作为别名,以便与
json 和 pickle 兼容。
pack 和 dump 将数据打包到文件类对象中。
unpack 和 load 从文件类对象中解包。
>>> import msgpack
>>> msgpack.packb([1, 2, 3])
'\x93\x01\x02\x03'
>>> msgpack.unpackb(_)
[1, 2, 3]请阅读 docstring 以了解选项。
Unpacker 是一个“流式解包器”。它从一个
流(或通过其 feed 方法提供的字节)中解包多个对象。
import msgpack
from io import BytesIO
buf = BytesIO()
for i in range(100):
buf.write(msgpack.packb(i))
buf.seek(0)
unpacker = msgpack.Unpacker(buf)
for unpacked in unpacker:
print(unpacked)也可以打包/解包自定义数据类型。下面是一个关于
datetime.datetime 的例子。
import datetime
import msgpack
useful_dict = {
"id": 1,
"created": datetime.datetime.now(),
}
def decode_datetime(obj):
if '__datetime__' in obj:
obj = datetime.datetime.strptime(obj["as_str"], "%Y%m%dT%H:%M:%S.%f")
return obj
def encode_datetime(obj):
if isinstance(obj, datetime.datetime):
return {'__datetime__': True, 'as_str': obj.strftime("%Y%m%dT%H:%M:%S.%f")}
return obj
packed_dict = msgpack.packb(useful_dict, default=encode_datetime)
this_dict_again = msgpack.unpackb(packed_dict, object_hook=decode_datetime)Unpacker 的 object_hook 回调函数接收一个字典;
可以使用 object_pairs_hook 回调函数来接收键值对列表。
注意:msgpack 目前可以把带时区的 datetime 编码为标准的 ext 类型。
请参阅 Packer docstring 中的 datetime 选项。
也可以使用 **ext** 类型来打包/解包自定义数据类型。
>>> import msgpack
>>> import array
>>> def default(obj):
... if isinstance(obj, array.array) and obj.typecode == 'd':
... return msgpack.ExtType(42, obj.tostring())
... raise TypeError("Unknown type: %r" % (obj,))
...
>>> def ext_hook(code, data):
... if code == 42:
... a = array.array('d')
... a.fromstring(data)
... return a
... return ExtType(code, data)
...
>>> data = array.array('d', [1.2, 3.4])
>>> packed = msgpack.packb(data, default=default)
>>> unpacked = msgpack.unpackb(packed, ext_hook=ext_hook)
>>> data == unpacked
True作为迭代的替代,Unpacker 对象提供了 unpack、
skip、read_array_header 和 read_map_header 方法。前两种方法
分别反序列化并返回结果,或忽略它,从流中读取整个消息。后两种方法返回
即将到来的容器中的元素数量,这样数组的每个元素,或映射的键值对,
都可以单独解包或跳过。
msgpack 的早期版本并没有区分字符串和二进制类型。 用于表示字符串和二进制类型的类型名为 **raw**。
你可以使用 use_bin_type=False
和 raw=True 选项来打包成旧规范,或从旧规范解包。
>>> import msgpack
>>> msgpack.unpackb(msgpack.packb([b'spam', 'eggs'], use_bin_type=False), raw=True)
[b'spam', b'eggs']
>>> msgpack.unpackb(msgpack.packb([b'spam', 'eggs'], use_bin_type=True), raw=False)
[b'spam', 'eggs']要使用 **ext** 类型,请将 msgpack.ExtType 对象传递给打包器。
>>> import msgpack
>>> packed = msgpack.packb(msgpack.ExtType(42, b'xyzzy'))
>>> msgpack.unpackb(packed)
ExtType(code=42, data='xyzzy')你可以将其与 default 和 ext_hook 一起使用。请参阅下方。
在反序列化来自不可靠来源的数据时,msgpack 提供了 两个安全选项。
max_buffer_size (默认值:100*1024*1024) 限制内部缓冲区大小。
它也用于限制预分配列表的大小。
strict_map_key (默认值:True) 将映射键的类型限制为 bytes 和 str。
虽然 MessagePack 规范没有限制映射键的类型,
但存在哈希拒绝服务攻击的风险。
如果你需要支持其他类型的映射键,请使用 strict_map_key=False。
CPython 的 GC 在分配的对象数量增长时启动。
这意味着反序列化可能会触发不必要的 GC。
你可以在反序列化大数据消息时使用 gc.disable()。
列表是 Python 中的默认序列类型。
然而,元组比列表更轻量。
当性能很重要时,你可以在反序列化时使用 use_list=False。
在 0.5 版本中,PyPI 上的包名称从 msgpack-python 更改为 msgpack。
从 msgpack-0.4 或更早版本升级时,请先运行 pip uninstall msgpack-python,
然后再运行 pip install -U msgpack。
-
Python 2 支持
-
扩展模块不再支持 Python 2。 纯 Python 实现(
msgpack.fallback)用于 Python 2。 -
msgpack 1.0.6 删除了对 Python 2.7 的官方支持,因为 pip 和 GitHub Action "setup-python" 不再支持 Python 2.7。
-
-
Packer
- Packer 默认使用
use_bin_type=True。 字节将以 bin 类型编码在 MessagePack 中。 - 已移除
encoding选项。UTF-8 始终被使用。
- Packer 默认使用
-
Unpacker
- Unpacker 默认使用
raw=False。它假定 str 值是有效的 UTF-8 字符串 并将其解码为 Python str(Unicode)对象。 encoding选项已移除。你可以使用raw=True来支持旧格式(例如,解包为 bytes 而不是 str)。- 为避免拒绝服务攻击,
max_buffer_size的默认值从 0 更改为 100 MiB。 如果你有大的但安全的数据,需要传入max_buffer_size=0。 - 为避免哈希拒绝服务攻击,
strict_map_key的默认值更改为 True。 如果你有包含非 bytes 或 str 类型映射键的数据,需要传入strict_map_key=False。
- Unpacker 默认使用