赞
踩
ProtoBuf: 是一套完整的 IDL(接口描述语言),出自Google,基于 C++ 进行的实现,开发人员可以根据 ProtoBuf 的语言规范生成多种编程语言(Golang、Python、Java 等)的接口代码,本篇只讲述 Python 的基础操作。据说 ProtoBuf 所生成的二进制文件在存储效率上比 XML 高 3~10 倍,并且处理性能高 1~2 个数量级,这也是选择 ProtoBuf 作为序列化方案的一个重要因素之一。
$ protoc --version
如果正常打印 libprotoc 的版本信息就表明 protoc 安装成功
$ pip install protobuf
创建 demo python 工程
在 example 包中编写 person.proto
- syntax = "proto3";
- package example;
-
- message person {
- int32 id = 1;
- string name = 2;
- }
-
- message all_person {
- repeated person Per = 1;
- }
进入 demo 工程的 example 目录,使用 protoc 编译 person.proto
- #! /usr/bin/env python
- # -*- coding: utf-8 -*-
- from example import person_pb2
-
- # 为 all_person 填充数据
- pers = person_pb2.all_person()
- p1 = pers.Per.add()
- p1.id = 1
- p1.name = 'xieyanke'
- p2 = pers.Per.add()
- p2.id = 2
- p2.name = 'pythoner'
-
- # 对数据进行序列化
- data = pers.SerializeToString()
-
- # 对已经序列化的数据进行反序列化
- target = person_pb2.all_person()
- target.ParseFromString(data)
- print(target.Per[1].name) # 打印第一个 person name 的值进行反序列化验证
1、python对序列化的字串反序列化为protobuf结构
注:其中用到的im_msg_body_pb2就是im_msg_body.proto文件经过编译后生成的python库文件。
- #!/usr/bin/python
- # -*- coding: utf-8 -*-
-
- import im_msg_body_pb2
-
- row_msg_body = b"\n\271\001\n!\010\000\020\223\203\321\363\005\030\343\337\232\334\007 \000(\n0\0008\206\001@\002J\006\345\256\213\344\275\223\022^\312\001[\nY\010\003\022\004\010\000\020\001(\0030\242\333\255\311\005H\225\340\215\320\n\212\001\017861684676539011\352\001.webim_2852155980_861684676539011_1584676769010\0224\n2\n0\345\275\223\346\227\266\347\273\231\346\210\221\344\273\213\347\273\215\347\232\204\346\227\266\345\200\231\350\257\264\344\270\200\346\254\241\346\200\247\351\200\200\345\256\214\345\225\212";
-
- print("----------实例结构对象,对原生字串反序列化-----------")
- msgbody = im_msg_body_pb2.MsgBody()
- msgbody.ParseFromString(row_msg_body)
- print(msgbody)
-
-
- print("---------------母结构赋值子结构----------------------")
- rich_text = im_msg_body_pb2.RichText()
- rich_text = msgbody.rich_text;
- print(rich_text)
-
- print("----------取repeated对象(Elem为repeated)------------")
- elem = im_msg_body_pb2.Elem();
- elem = msgbody.rich_text.elems[1]
- print(elem)
-
- print("----------------下面打印的就是汉字了------------------")
- text = im_msg_body_pb2.Text();
- text = msgbody.rich_text.elems[1].text
- print(text.str)
-
- print("--------------------结构拷贝-------------------------")
- msgbody2 = im_msg_body_pb2.MsgBody()
- msgbody2.rich_text.CopyFrom(msgbody.rich_text)
- print('msgbody2:\n', msgbody2)
2、python操作protobuf中repeated修饰的数据(给repeated字段赋值)
切记两个点:(1)对于repeated的结构使用.add() (2)对于单个元素使用append()追加
Python序列化proto中repeated修饰的数据 - YYRise - 博客园
3、python判断某个字段是否存在(子字段&子结构)
- #判断elem实例对象中是否有text字段(最终字段可以这样;子结构貌似不可以)
- if elem.text != None:
- print(elem.text)
-
- #对于子结构这里先提供一个不是很美观但是能用的方法
- #那就是用这个子结构和ph创建的空这个子结构对比,如下:
- if msg_body.rich_text==im_msg_body_pb2.MsgBody().rich_text:
- print("rich_text is empty!!")
4、python循环遍历某个repeated字段
- #for循环遍历msgbody→rich_text→elems(repeated)
- for elem in msgbody.rich_text.elems:
- print(elem)
5、获取某个repeated字段的size
- #使用python的len函数即可
- print("length:",len(msgbody.rich_text.elems))
6、按序号取repeated字段的值
- #使用中括号"[]"
- for i in range(0,len(msgbody.rich_text.elems)):
- print("elems[",i,"]",msgbody.rich_text.elems[i])
7、赋值一个结构过来 —— CopyFrom
- msgbody2 = im_msg_body_pb2.MsgBody()
- msgbody2.rich_text.CopyFrom(msgbody.rich_text)
- print('msgbody2:\n', msgbody2)
8、proto3的map的使用
官网→python→Guide→Map Fields一下就找到使用举例了。这里
晚点继续完善python对于protobuf常用的操作。。。。
其实最高效快速的方式就是看官方使用手册(啥都有)。
Protocol Buffer Basics: Python | Protocol Buffers | Google Developers
Python Generated Code | Protocol Buffers | Google Developers
这里先贴两个python常用操作protobuf的链接,后续整理一下。
1、“Couldn't build proto file into descriptor pool ”,大致如下:
正解如下:这是protobuf二进制轮子的问题,解决该问题的唯一方法是安装纯python的实现。具体如下:
- pip uninstall protobuf
- pip install --no-binary=protobuf protobuf
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。