MessagePack (Python第三方库文档翻译)

田博易
2023-12-01

MessagePack (Python第三方库文档翻译)
发行时间: Dec 18, 2020
官网:https://pypi.org/project/msgpack/
什么是MessagePack
MessagePack是一个高效的二进制序列化格式,它可以像JSON一样在众多语言之间交换信息。但MessagePack比JSON更快、更轻巧。这个包裹给CPython bindings提供读写MessagePack数据的功能。
对于使用者非常重要的通知
1:从0.5版本开始MessagePack在python第三方库中的名字从
msgpack-python更改为msgpack
2:从0.4版本或更早的版本更新时需要先pip uninstall msgpack-python 之后再 pip install -U msgpack。
与旧版的兼容性
1:在旧版MessagePack中,你可以使用use_bin_type=False选项将字节对象打包成原始类型,来代替新版MessagePack中二进制类型。
2:可以使用raw=True选项解包旧的msgpack格式。它将msgpack中的原始的字符串类型解压为Python字节。
详情见以下注释。
msgpack 1.0的重大突破性变化
python2:扩展模块不再支持Python2。纯Python实现(msgpack.fallback)被用于用于Python2。
Packer:
1:默认use_bin_type=True,在msgpack中字节被编码成二进制类型。如过你仍然使用python2,对于所用的string类型都要是用unicode。你可以使用use_bin_type=False编成旧的msgpack形式。
2:encoidng选项已移除,总是使用utf-8
unpacker
1:默认情况下,raw=False。它假设字符串类型是有效的UTF-8字符串,并将它们解码为Python 字符串(unicode)对象。
2:已删除encoding选项。可以使用raw=True来支持旧格式。
3:最大缓冲区大小的默认值从0更改为100 MiB
4:strict_map_key的默认值更改为True以避免hashdos。如果数据中包含的字典中的键的类型不是bytes或str,则需要传递strict_map_key=False。
安装:
$ pip install msgpack
纯Python实现
msgpack(msgpack._cmsgpack)中的扩展模块不支持Python 2和PyPy.。但是msgpack为PyPy 和python2提供了一个纯Python实现(msgpack.fallback)。由于pip使用纯Python实现,因此在可预见的将来不会放弃对python2的支持。
Windows
如果无法使用二进制发行版,则需要在Windows上安装Visual Studio或Windows SDK。没有扩展,在CPython上使用纯Python实现运行缓慢。
如何使用
注意:在下面的示例中,对于使用msgpack<1.0的用户,我使用raw=False和use_bin_type=True。这些选项是msgpack 1.0的默认选项,因此您可以忽略它们。
当前版本:msgpack 1.0.2
一次性打包与解包
使用packb打包和unpackb解包,为兼容python中json库和pickle库中dumps和loads方法msgpack也拥有dumps和loads方法。
pack和dump打包到一个类文件对象中,unpack和load在这里插入代码片把一个类文件对象解包。

>>> import msgpack
>>> msgpack.packb([1, 2, 3], use_bin_type=True)
'\x93\x01\x02\x03'
>>> msgpack.unpackb(_, raw=False)
[1, 2, 3]

unpack方法可以把msgpack的一个数组解包成一个列表,也可解包元组

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

为了向后兼容,您应该始终指定use_list关键字参数。请参阅下面有关use_list option的性能问题。
阅读docstring以获取其他选项。
流式解包
Unpacker是一个流式解包器,它可以从一个流中解包多种对象(也可以是由feed方法提供的字节流)

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)  # 打印出0到99总共100个数字

自定义数据类型的打包/解包
也可以打包/解包自定义数据类型。下面是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

# msgpack.packb中default等各种参数的使用详见python中的JSON库\
# 可查看官方文档了解各种参数的含义
packed_dict = msgpack.packb(useful_dict, default=encode_datetime, use_bin_type=True)
this_dict_again = msgpack.unpackb(packed_dict, object_hook=decode_datetime, raw=False)

扩展类型
msgpack可以打包/解包自定义扩展数据类型。(可理解为python中的第三``方库而非python的官方库)

>>> 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)
>>> 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', u'eggs'], use_bin_type=False), raw=True)
[b'spam', b'eggs']
>>> msgpack.unpackb(msgpack.packb([b'spam', u'eggs'], use_bin_type=True), raw=False)
[b'spam', 'eggs']

ext type
使用ext type传msgpack.ExtType对象到解包器(packer)

>>> import msgpack
>>> packed = msgpack.packb(msgpack.ExtType(42, b'xyzzy'))
>>> msgpack.unpackb(packed)
ExtType(code=42, data='xyzzy')

您可以将它与default和ext_hook一起使用。见下文。
安全
为了从不可靠源接收的数据解包,msgpack提供了两个安全选项。
1:最大缓冲区大小(默认值:10010241024)限制内部缓冲区大小,它还用于限制预分配的列表大小。
2:严格的映射键(默认值:True)将字典键的类型限制为bytes和str。虽然msgpack规范没有限制字典键的类型,但存在hashdos的风险。如果需要为映射键支持其他类型,请使用strict_map_key=False。

>>> useful_dict={'id': 1, 3: 4}
>>> b=msgpack.dumps(useful_dict)
>>> msgpack.loads(b,strict_map_key=False)
{'id': 1, 3: 4}
>>> msgpack.loads(b)
Traceback (most recent call last):
  File "<pyshell#176>", line 1, in <module>
    msgpack.loads(b)
  File "msgpack\_unpacker.pyx", line 195, in msgpack._cmsgpack.unpackb
ValueError: int is not allowed for map key

性能提示

CPython的GC在增长分配的对象时开始。这意味着解包使可能会导致无用的GC。解包大消息时可以使用gc.disable()。

列表是Python的默认序列类型,但元组比列表轻巧,在看重效率的时候,可以在解包时使用use_list=False。

 类似资料: