MessagePack

本文最后更新于:2020年12月9日 下午

信息

MessagePack是一种有效的二进制序列化格式
相比与于JSON,它处理起来更快,生成的文件也更小
小整数被编码为一个字节,典型的短字符串除字符串本身外仅需要一个额外的字节

但是这东西的问题其实也很多

  • 兼容性问题。不同语言的客户端的不同版本经常发生兼容性
  • 对于二进制安全需求,json有base64方案。事实上,浏览器就对base64友好
  • 对于rpc序列化需求,高性能有protobuf,后面有json,并没有很大的优势

官网:https://msgpack.org/

安装

1
pip install msgpack

使用

pack & unpack 打包与解包

1
2
3
4
5
6
7
8
import msgpack
# 打包函数packb,类似于json.dumps
msgpack.packb([1, 2, 3], use_bin_type=True)
# 此处得到结果:'\x93\x01\x02\x03'

# 解包函数unpackb,类似于json.loads
msgpack.unpackb(_, raw=False)
# 此处得到结果:[1, 2, 3]

此处的解包函数得到的结果是一个List,如果希望得到的是tunple可以添加参数

1
2
msgpack.unpackb(b'\x93\x01\x02\x03', use_list=False, raw=False)
(1, 2, 3)

Streaming unpacking 流解包

1
2
3
4
5
6
7
8
9
10
11
12
13
import msgpack
from io import BytesIO

# 向流中写入一些内容以用作试验
buf = BytesIO()
for i in range(100):
buf.write(msgpack.packb(i, use_bin_type=True))

buf.seek(0)

unpacker = msgpack.Unpacker(buf, raw=False)
for unpacked in unpacker:
print(unpacked)

解包函数可以从流(或从通过其feed方法提供的字节)中解出多个对象

自定义类型

使用ext能够扩充打包/解包的类型

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
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, use_bin_type=True)
unpacked = msgpack.unpackb(packed, ext_hook=ext_hook, raw=False)
print(data == unpacked)
# True

解包控制

1
2
3
4
5
6
7
8
9
10
11
12
13
from io import BytesIO

def distribute(unpacker, get_worker):
nelems = unpacker.read_map_header()
for i in range(nelems):
# Select a worker for the given key
key = unpacker.unpack()
worker = get_worker(key)

# Send the value as a packed message to worker
bytestream = BytesIO()
unpacker.skip(bytestream.write)
worker.send(bytestream.getvalue())

本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!