当前位置:   article > 正文

Python 操作 protobuf 常见用法_python proto

python proto

ProtoBuf: 是一套完整的 IDL(接口描述语言),出自Google,基于 C++ 进行的实现,开发人员可以根据 ProtoBuf 的语言规范生成多种编程语言(Golang、Python、Java 等)的接口代码,本篇只讲述 Python 的基础操作。据说 ProtoBuf 所生成的二进制文件在存储效率上比 XML 高 3~10 倍,并且处理性能高 1~2 个数量级,这也是选择 ProtoBuf 作为序列化方案的一个重要因素之一。

1、protoc安装

  1. 安装 protoc :Protoc下载地址,可以根据自己的系统下载相应的 protoc,windows 用户统一下载 win32 版本。
  2. 配置 protoc 到系统的环境变量中,执行如下命令查看是否安装成功:

$ protoc --version
如果正常打印 libprotoc 的版本信息就表明 protoc 安装成功

  1. 安装 ProtoBuf 相关的 python 依赖库

$ pip install protobuf

2、python语言的使用(参见官网)

 2.1、创建demo工程

  1. 创建 demo python 工程

  2. 在 example 包中编写 person.proto

    1. syntax = "proto3";
    2. package example;
    3. message person {
    4. int32 id = 1;
    5. string name = 2;
    6. }
    7. message all_person {
    8. repeated person Per = 1;
    9. }
  3. 进入 demo 工程的 example 目录,使用 protoc 编译 person.proto

  1. 在 python 工程中使用 protobuf 进行序列化与反序列化
    main.py:
    1. #! /usr/bin/env python
    2. # -*- coding: utf-8 -*-
    3. from example import person_pb2
    4. # 为 all_person 填充数据
    5. pers = person_pb2.all_person()
    6. p1 = pers.Per.add()
    7. p1.id = 1
    8. p1.name = 'xieyanke'
    9. p2 = pers.Per.add()
    10. p2.id = 2
    11. p2.name = 'pythoner'
    12. # 对数据进行序列化
    13. data = pers.SerializeToString()
    14. # 对已经序列化的数据进行反序列化
    15. target = person_pb2.all_person()
    16. target.ParseFromString(data)
    17. print(target.Per[1].name) # 打印第一个 person name 的值进行反序列化验证

 2.2、更多操作

1、python对序列化的字串反序列化为protobuf结构

注:其中用到的im_msg_body_pb2就是im_msg_body.proto文件经过编译后生成的python库文件。

  1. #!/usr/bin/python
  2. # -*- coding: utf-8 -*-
  3. import im_msg_body_pb2
  4. 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";
  5. print("----------实例结构对象,对原生字串反序列化-----------")
  6. msgbody = im_msg_body_pb2.MsgBody()
  7. msgbody.ParseFromString(row_msg_body)
  8. print(msgbody)
  9. print("---------------母结构赋值子结构----------------------")
  10. rich_text = im_msg_body_pb2.RichText()
  11. rich_text = msgbody.rich_text;
  12. print(rich_text)
  13. print("----------取repeated对象(Elem为repeated)------------")
  14. elem = im_msg_body_pb2.Elem();
  15. elem = msgbody.rich_text.elems[1]
  16. print(elem)
  17. print("----------------下面打印的就是汉字了------------------")
  18. text = im_msg_body_pb2.Text();
  19. text = msgbody.rich_text.elems[1].text
  20. print(text.str)
  21. print("--------------------结构拷贝-------------------------")
  22. msgbody2 = im_msg_body_pb2.MsgBody()
  23. msgbody2.rich_text.CopyFrom(msgbody.rich_text)
  24. print('msgbody2:\n', msgbody2)

2、python操作protobuf中repeated修饰的数据(给repeated字段赋值)

切记两个点:(1)对于repeated的结构使用.add()  (2)对于单个元素使用append()追加

Python序列化proto中repeated修饰的数据 - YYRise - 博客园

3、python判断某个字段是否存在(子字段&子结构)

  1. #判断elem实例对象中是否有text字段(最终字段可以这样;子结构貌似不可以)
  2. if elem.text != None:
  3. print(elem.text)
  4. #对于子结构这里先提供一个不是很美观但是能用的方法
  5. #那就是用这个子结构和ph创建的空这个子结构对比,如下:
  6. if msg_body.rich_text==im_msg_body_pb2.MsgBody().rich_text:
  7. print("rich_text is empty!!")

4、python循环遍历某个repeated字段

  1. #for循环遍历msgbody→rich_text→elems(repeated)
  2. for elem in msgbody.rich_text.elems:
  3. print(elem)

5、获取某个repeated字段的size

  1. #使用python的len函数即可
  2. print("length:",len(msgbody.rich_text.elems))

6、按序号取repeated字段的值

  1. #使用中括号"[]"
  2. for i in range(0,len(msgbody.rich_text.elems)):
  3. print("elems[",i,"]",msgbody.rich_text.elems[i])

7、赋值一个结构过来 —— CopyFrom

  1. msgbody2 = im_msg_body_pb2.MsgBody()
  2. msgbody2.rich_text.CopyFrom(msgbody.rich_text)
  3. 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的链接,后续整理一下。

参考一  参考二

3、可能遇到的问题

1、“Couldn't build proto file into descriptor pool ”,大致如下:

正解如下:这是protobuf二进制轮子的问题,解决该问题的唯一方法是安装纯python的实现。具体如下:

  1. pip uninstall protobuf
  2. pip install --no-binary=protobuf protobuf

参照:https://github.com/ValvePython/csgo/issues/8

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/正经夜光杯/article/detail/1009086
推荐阅读
相关标签
  

闽ICP备14008679号