protobuf 安装

protobuf 分为 2 和 3
  • protoc 下载地址 需要根据自己平台下载不同版本(windows 就下载下面这个)

  • 加入环境变量
  • 测试一下 protoc --version
  • pip install protobuf python 需要安装模块

protobuf 常见数据类型

这里列举了一些常用的数据类型
类型说明
string字符串类型,要求utf-8或7-bit与ascii编码的字符串
bytes比特类型
bool布尔类型
int3232位整形
int6464位整形
float浮点类型
repeated数组(列表)
mapmap(字典类型)

protobuf 特殊字符

类型说明
package包名
syntaxProtobuf版本
service定义服务
rpc定义服务中方法
stream定义的方法传输为流传输
message定义消息体 message User{}
extend拓展消息体 extend User{}
import导入插件
//注释

实例

下面是一个完整的 Demo 例子

流程:

  1. 先配置好 proto 文件
  2. 终端下执行 protoc --python_out=./ addressbook.proto 得到 pb2.py 文件
  3. 编写测试 python 代码, 执行效果如下
当然也可以用下面方法编译 pb 文件
protoc --descriptor_set_out=./addressbook.pb ./addressbook.proto

syntax = "proto3";
package test;

message AddressBook {
  repeated Person people = 1;
}

message Person {
  string name = 1;
  int32 id = 2;
  string email = 3;
  bool work_status = 4;
  repeated PhoneNumber phones = 5;
  repeated Money money = 6;
  repeated string girlfriend = 7;
  MyMessage maps = 8;
  bytes byte=9;
}

message PhoneNumber {
  string number = 1;
  PhoneType type = 2;
}
message Money {
  float ch = 1;
  float us = 2;
}

enum PhoneType {
  MOBILE = 0;
  HOME = 1;
  WORK = 2;
}


message MyMessage {
  map<int32, int32> mapfield = 1;
}

#! /usr/bin/env python
from protobuf import addressbook_pb2

# 实例化对象
address_book = addressbook_pb2.AddressBook()


def Serialize_To_String():
    person = address_book.people.add()

    person.id = 1
    person.name = "Zok"
    person.email = "362416272@qq.com"
    person.work_status = True

    # person_money = person.money.add()
    # person_money.us = 1000
    # person_money.ch = 2000
    # 也可以直接写
    person.money.add(ch=2000, us=1000)
    person.money.add(ch=3000, us=4000)

    person.girlfriend.append('Baby')
    person.girlfriend.extend(["Luci", "CoCo"])

    phone_number = person.phones.add()
    phone_number.number = "13999999999"
    phone_number.type = addressbook_pb2.MOBILE

    maps = person.maps
    maps.mapfield[1] = 1
    maps.mapfield[2] = 2

    person.byte = bytes('我是吴彦祖', encoding='utf-8')

    # 序列化
    serializeToString = address_book.SerializeToString()
    print(serializeToString, type(serializeToString))
    with open('addressBook.bin', 'wb') as f:
        f.write(serializeToString)
    address_book.ParseFromString(serializeToString)


def Parse_From_String():
    with open('addressBook.bin', 'rb') as f:
        address_book.ParseFromString(f.read())  # 读取
    for person in address_book.people:
        msg = """
id: {}
name: {}
email: {}
work_status: {}""".format(person.id, person.name, person.email, person.work_status)
        print(msg)

        for m in person.money:  # 数组遍历输出,
            print(m.ch, m.us)
        for phone_number in person.phones:  # 遍历多个号码
            print(phone_number.number, phone_number.type)
        for key in person.maps.mapfield:  # 遍历 map 字典
            print(key, person.maps.mapfield[key])
        for girl in person.girlfriend:
            print(girl)
        print('byte:', person.byte.decode())  # byte 类型编码


if __name__ == '__main__':
    Serialize_To_String()
    Parse_From_String()

反序列化

在我们没有拿到头文件的时候,我们只能查看无key状态下的值,以python为例,查看方法如下
import subprocess


def decode(data):
    process = subprocess.Popen([r'D:\othter\protoc-3.15.6-win64\bin\protoc.exe', '--decode_raw'],
                               stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)

    output = error = None
    try:
        output, error = process.communicate(data)
    except OSError:
        pass
    finally:
        if process.poll() != 0:
            process.wait()
    return output


with open('addressBook.bin', 'rb') as f:
    data = f.read()  # 读取
print(str(decode(data), encoding="utf-8"))

想要彻底还原的话,需要找到配置文件,或者仿造配置文件

Last modification:March 18, 2021
如果觉得我的文章对你有用,请随意赞赏