什么是MessagePack?

It’s like JSON. but fast and small。
MessagePack is an efficient binary serialization format. It lets you exchange data among multiple languages like JSON. But it’s faster and smaller. Small integers are encoded into a single byte, and typical short strings require only one extra byte in addition to the strings themselves.

这是官网对于MessagePack的描述,可见这是一种类似JSON格式,但是比JSON更快更小的高效二进制序列化数据传输格式。它可以像JSON一样在多种语言之间交换数据。
小的整数被编码成单个字节,典型的短字符串除了字符串本身之外只需要一个额外的字节进行描述。

这是官方的示意图,同样的数据,使用JSON格式占用27bytes,使用MessagePack只占用18bytes。从图中可以看出,MessagePack对数据进行了重新编码和压缩,如,去掉了花括号、冒号、引号等符号,改用对应编码来描述数据的结构。如82表示这是一个包含两个元素的map,A7中A表示string,7表示长度,后面则是字符串数据内容,C3表示布尔值true等。同时使用二进制传输,
这样就大大减少了无用字符的数量,压缩了数据所占用的空间,在网络传输等情况下提供更快的速度。

对于MessagePack压缩原理感兴趣可以阅读:https://github.com/msgpack/msgpack/blob/master/spec.md


MessagePack支持的语言:

现在MessagePack支持超过50种编程语言和应用环境,可以在官网查看支持的实现列表。

单就对于Python的支持就提供了msgpack, vsergeev, lekma, jakm, polyglotted, aviramha等多个库以供使用。

Redis、fluentd、Celery等软件也提供对MessagePack格式的支持。

下面我们介绍MessagePack官方提供的Python库:msgpack。


msgpack python库的使用:

项目地址:https://github.com/msgpack/msgpack-python

提示:msgpack从1.0版本开始不再支持python2,如果想在python2中使用msgpack可以使用msgpack.fallback库,不过该库是纯python实现,相比于使用 C 语言做 binding 的msgpack 库会慢很多。

进入正题,如何在Python3中使用msgapck进行消息传输?

  • 安装:pip install msgpack
  • 使用:
  1. 一次性打包和解包:
    使用packb方法打包,使用unpackb方法解包。同时msgpack还提供了dumpsloads方法作为这两个方法的别名,以兼容json库和pickle库。

    import msgpackdata = {'name': 'Jack', 'age': 20}# pack
    pack_data = msgpack.packb(data)
    print(pack_data)
    pack_data = msgpack.dumps(data)
    print(pack_data)# unpack
    unpack_data = msgpack.unpackb(pack_data)
    print(unpack_data)
    unpack_data = msgpack.loads(pack_data)
    print(unpack_data)
    

    执行结果:

    b'\x82\xa4name\xa4Jack\xa3age\x14'
    b'\x82\xa4name\xa4Jack\xa3age\x14'
    {'name': 'Jack', 'age': 20}
    {'name': 'Jack', 'age': 20}
    

    当数据装包含列表时,解包时默认解包为list,如果设置use_list=False,则解包为元组。
    List是python默认的序列类型,但是元组比列表要“轻”,当性能对于程序很重要时,可以在解包时使用use_list=False

    import msgpackdata = [1, 2, 3, 4]pack_data = msgpack.packb(data)
    print(pack_data)unpack_data = msgpack.unpackb(pack_data)
    print(unpack_data)unpack_data = msgpack.unpackb(pack_data, use_list=False)
    print(unpack_data)
    

    执行结果:

    b'\x94\x01\x02\x03\x04'
    [1, 2, 3, 4]
    (1, 2, 3, 4)
    
  2. 对流进行解包Streaming unpacking:
    Unpacker是一个streaming unpacker。它从一个流中解包多个对象(或者从其提要方法提供的字节中解包)。

    import msgpack
    from io import BytesIO# write msgpack to stream
    buf = BytesIO()
    for i in range(10):buf.write(msgpack.packb(i))buf.seek(0)# read and unpack msgpack from stream
    unpacker = msgpack.Unpacker(buf)
    for unpacked in unpacker:print(unpacked, end='\t')
    

    执行结果:

    0  1   2   3   4   5   6   7   8   9
    

    同样, 可以使用Unpacker从文件流中读取和解包数据:

    import msgpack# write msgpack to file
    with open('data', 'wb') as f:for i in range(10):f.write(msgpack.packb(i))# read and unpack msgpack from file
    with open('data', 'rb') as f:unpacker = msgpack.Unpacker(f)for unpacked in unpacker:print(unpacked, end='\t')
    

    执行结果:

    0  1   2   3   4   5   6   7   8   9
    
  3. 对自定义数据类型进行打包/解包:
    msgpack也可以对自定义的数据类型解析处理,需要提供对应的处理方法作为参数传给packbunpackb。这里以datetime.datetime为例:

    import msgpack
    import datetimedata = {'id': 1, 'created': datetime.datetime.now()}def encode_datetime(obj):"""对datetime数据进行编码"""if isinstance(obj, datetime.datetime):return {'__datetime__': True, 'as_str': obj.strftime('%Y%m%dT%H%M%S.%f')}return objdef decode_datetime(obj):"""对datetime数据进行解码"""if '__datetime__' in obj:obj = datetime.datetime.strptime(obj['as_str'], '%Y%m%dT%H%M%S.%f')return objpacked_data = msgpack.packb(data, default=encode_datetime)
    unpacked_data = msgpack.unpackb(packed_data, object_hook=decode_datetime)
    print(packed_data)
    print(unpacked_data)
    print(data == unpacked_data)
    

    执行结果:

    b'\x82\xa2id\x01\xa7created\x82\xac__datetime__\xc3\xa6as_str\xb620220607T185631.676527'
    {'id': 1, 'created': datetime.datetime(2022, 6, 7, 18, 56, 31, 676527)}
    True
    

    其中,Unpackerobject_hook回调接收字典对象,object_pairs_hook回调可以用来接收键值对的列表。

  4. 扩展类型:
    还可以使用 ext类型对自定义数据类型进行打包和解包。

    import msgpack
    import arraydef default(obj):if isinstance(obj, array.array) and obj.typecode == 'd':return msgpack.ExtType(42, obj.tobytes())raise TypeError('Unknown Type: %r' % obj)def ext_hook(code, data):if code == 42:a = array.array('d')a.frombytes(data)return a raise msgpack.ExtType(code, data)data = array.array('d', [1.2, 3.4, 5.6])
    packed = msgpack.packb(data, default=default)
    unpacked = msgpack.unpackb(packed, ext_hook=ext_hook)
    print(packed)
    print(unpacked)
    print(data == unpacked)
    

    执行结果:

    b'\xc7\x18*333333\xf3?333333\x0b@ffffff\x16@'
    array('d', [1.2, 3.4, 5.6])
    True
    
  5. 专业解包控制:
    作为对迭代的替代,Unpacker 提供了 unpackskipread_array_headerread_map_header 方法。前两个从流中读取整个消息,分别对结果进行反序列化和返回,或者忽略它。后两个方法返回即将到来的容器中的元素数量,以便数组中的每个元素或map中的键值对可以单独解包或跳过。

  • 注意:
    msgpack不强制区分 bytes 和 str,二者都可以进行打包和解包。
  • 安全问题:
    如果要解包来自于不信任的数据源信息,msgpack提供了两个安全选项:

    • max_buffer_size (默认: 100*1024*1024) 限制内部缓冲区大小。它也用于限制预分配的列表大小。
    • strict_map_key (默认: True) 将map的键类型限制为bytes和 str。虽然 msgpack 规范没有限制映射键的类型,但是存在 hashdos 的风险。如果需要支持其他类型的映射键,设置 strict_map_key = False
  • 性能提醒:
    CPython的GC(垃圾回收)会在增加分配对象时开始执行。这意味着解包时可能会造成无用的GC。你可以在解包大的消息时设置gc.disable()

MessagePack简介与在Python中使用msgpack相关推荐

  1. python简介怎么写-python中如何写类

    类的定义 Python中,定义类是通过class关键字,例如我们定义一个存储学生信息的类: class Student(object): pass class后面紧接着是类名,即Student,类名通 ...

  2. 转:HTTP协议简介与在python中的使用详解

    1. 使用谷歌/火狐浏览器分析 在Web应用中,服务器把网页传给浏览器,实际上就是把网页的HTML代码发送给浏览器,让浏览器显示出来.而浏览器和服务器之间的传输协议是HTTP,所以: HTML是一种用 ...

  3. python中prettytable模块_Python库: PrettyTable 模块

    一 PrettyTable简介 PrettyTable是python中的一个第三方库,可用来生成美观的ASCII格式的表格: 二 PrettyTable安装 使用PIP即可十分方便的安装PrettyT ...

  4. [转载] python中字典copy_python深度复制字典,copy方法与deepcopy方法

    参考链接: Python字典copy() 简介 INTRODUCTION掌握python中字典数据的赋值处理,掌握指针到底在哪里?... 本篇文章创作主要是为了让小伙伴们掌握普通字典的赋值.字典的co ...

  5. python中prettytable模块_PrettyTable模块

    一.简介 PrettyTable 是python中的一个第三方库,可用来生成美观的ASCII格式的表格. 二.安装 pip install prettytable 三.导入 from prettyta ...

  6. Python中tkinter库

    1. 简介 Tkinter是Python中常用的GUI库,它使用Tk GUI工具包,并提供了创建各种GUI应用程序的功能. 2. 创建一个窗口 要创建一个窗口,需要通过导入Tkinter模块,创建一个 ...

  7. 如何用Python中Tushare包轻松完成股票筛选(详细流程操作)

    如何用Python中Tushare包轻松完成股票筛选(详细流程操作) 本文包括安装以及调用Tushare包的详细流程操作 一.Tushare简介 Tushare是Python中一个十分好用的免费调用股 ...

  8. 警惕: Python 中的路径穿越

    简介 谈到 Python 中的路径拼接,大家会想到什么? os pathlib 以上两个模块都是 Python 内置的模块,可以很方便的帮助我们完成路径的拼接而不需要担心不同系统下的路径格式问题,但却 ...

  9. python中临时文件及文件夹使用

    python中临时文件及文件夹使用 文章目录 python中临时文件及文件夹使用 一.简介 二.临时文件夹 2.1 获取临时文件夹 2.2 生成临时文件夹 三.临时文件 3.1 生成不自动删除(关闭时 ...

最新文章

  1. Linux下nginx支持.htaccess文件实现伪静态的方法!
  2. 1.为什么要学习MATLAB
  3. 查询去重_如何在 1 秒内做到大数据精准去重?
  4. html表单中get与post之间的区别
  5. keil5图标变成白色_电脑桌面图标全部变成白色的解决办法
  6. MaxCompute 多租户数据安全体系
  7. LeetCode刷题(28)
  8. 【WCF】错误处理(二):错误码―—FaultCode
  9. RTCP协议解析--RR
  10. cgroup学习(七)——cpu子系统
  11. 面向对象的三个基本特征_杂谈:JavaScript面向对象
  12. vivox6Android版本,vivo x6有几个版本?vivo x6各版本区别对比评测
  13. ad域控服务器教程,VMware搭建配置AD域服务器的方法步骤(图文教程)
  14. 电机扭矩计算公式T=9550*P/n
  15. NitroShare 是一个局域网文件传输工具,支持 Windows、OS X 和 Linux。基于 Qt 开发。
  16. 计算机描绘的基因结构图,推荐一款好用的基因结构图在线绘制工具!
  17. matlab模拟塞曼图谱,C.基于LabVIEW的塞曼效应虚拟仿真-中国高等学校实验物理教学研究会.ppt...
  18. 【笔记整理】node.js笔记
  19. 老司机开车|消费升级如何具体化?
  20. 企业微信实现扫码登录

热门文章

  1. 中国农历的Java实现
  2. PAT乙级 1069 微博转发抽奖 (20 分) C语言
  3. Tomoya【省选模拟赛】
  4. 视频教程-数据分析与数据挖掘导论(R语言)-MySQL
  5. wps2013抢先版下如何删除轻办公
  6. ThinkServer RD640 设置RAID1
  7. 【07月03日】A股ROE最高排名
  8. VLCMediaPlayer
  9. 权健涉嫌传销犯罪被立案侦查,周洋父亲:很快会提起诉讼
  10. DesktopGoose的下载和使用(抖音网红桌宠鹅)【保姆级教程】