Google Protocol Buffers(简称 Protobuf)是一种由 Google 开发的数据序列化格式,用于定义结构化数据并在不同的系统或编程语言之间高效地传输和存储数据。它可以看作是一种更轻量且更高效的替代方案,类似于 XML 或 JSON,但在性能和数据大小上表现更优。其使用步骤如下:
- 安装 Protocol Buffers 编译器
- 编写 .proto 文件:定义数据结构
- 编译 .proto 文件:使用编译器将 .proto 文件编译为目标语言代码。
- 在代码中使用生成的文件:创建和操作数据对象,实现序列化和反序列化。
1. 安装配置
Protobuf 的安装需要两样东西:一个是 protobuf 编译器,一个是 python 进行 protobuf 数据操作的依赖包。首先,通过下面的链接下载自己平台的 protobuf 编译器:
GitHub:https://github.com/protocolbuffers/protobuf
Releases:https://github.com/protocolbuffers/protobuf/releases
下载之后的文件结构如下:
├───bin
│       protoc.exe
│
└───include
    └───google
        └───protobuf
            │   any.proto
            │   api.proto
            │   cpp_features.proto
            │   descriptor.proto
            │   duration.proto
            │   empty.proto
            │   field_mask.proto
            │   java_features.proto
            │   source_context.proto
            │   struct.proto
            │   timestamp.proto
            │   type.proto
            │   wrappers.proto
            │
            └───compiler
                    plugin.proto
- bin 目录下的 protoc.exe 就是我们需要的编译器
- include 目录下是常用 Protobuf 数据类型或功能
将 bin 目录配置到 PATH 环境变量中,最后输入下面命令检查编译器是否可用:
protoc --version
接下来,再安装 Python Protobuf 依赖包(我这里使用 5.28.3 版本):
pip install protobuf==5.28.3 -i https://pypi.tuna.tsinghua.edu.cn/simple/
注意:protobuf 编译器版本和 python protobuf 库的版本要保持一致。我们可以从 Protobuf 编译器生成的 Python 文件的顶部注释中查看对应的版本。例如:
# -*- coding: utf-8 -*- # Generated by the protocol buffer compiler. DO NOT EDIT! # NO CHECKED-IN PROTOBUF GENCODE # source: protos/developer.proto # Protobuf Python Version: 5.28.3 """Generated protocol buffer code."""
2. 使用示例
2.1 数据定义
创建 demo.proto 文件,定义数据如下:
syntax = "proto3";
enum Week
{
    Mon = 0;
    Tue = 1;
    Wed = 2;
    Thu = 3;
    Fri = 4;
    Sat = 5;
    Sun = 6;
}
message Custom
{
    int32 attr1 = 1;
    int32 attr2 = 2;
}
message Demo
{
    string name = 1;
    int32 numb = 2;
    Week week = 3;
    repeated int32 rept = 4;
    map<string, int32> mpsi = 5;
    Custom cust = 6;
}
使用下面的命令编译 proto 文件:
protoc *.proto --python_out=pyi_out:.
每个 proto 文件会生成两种不同的文件:
- foo_pb2.py: 实际使用的模块文件
- foo_pb2.pyi:用于提供静态类型信息提示
2.2 数据操作
在 Protobuf 中 SerializeToString 函数可以将 Python 数据对象序列化为二进制数据(字节类型),ParseFromString 函数可用以将二进制数据反序列化为 Python 数据对象。
from demo_pb2 import Demo, Week, Custom
from google.protobuf import json_format
# 1. 对象操作
def test01():
    demo = Demo()
    # 1. 基本类型
    demo.name = "张三"
    demo.numb = 200
    demo.week = Week.Thu
    # 2. 自定义类型
    demo.cust.attr1 = 100
    demo.cust.attr2 = 200
    # 3. repeated 类型
    demo.rept.append(10)
    demo.rept.append(20)
    demo.rept.insert(1, 30)
    # 4. map 类型
    demo.mpsi['k1'] = 100
    demo.mpsi['k2'] = 200
    demo.mpsi['k3'] = 300
    print(demo)
    # 5. 其他方法
    print('对象大小:', demo.ByteSize())
    # demo = Demo(name="张三",
    #             numb=100,
    #             week=Week.Thu,
    #             rept=[10, 20, 30],
    #             mpsi={'v1': 100, 'v2': 200},
    #             cust=Custom(attr1=11, attr2=22))
# 2. 对象序列化
def test02():
    demo = Demo(name='张三',
                numb=100,
                week=Week.Thu,
                rept=[10, 20],
                mpsi={'v1': 100, 'v2': 200},
                cust=Custom(attr1=11, attr2=22))
    # 1. 序列化为二进制数据
    data = demo.SerializeToString()
    print(data)
    open('data.bin', 'wb').write(data)
    # 2. 序列化为 json 格式
    json = json_format.MessageToJson(demo)
    print(json)
    open('data.json', 'w').write(json)
# 3. 对象反序列化
def test03():
    # 1. 反序列化二进制数据
    demo = Demo()
    data = open('data.bin', 'rb').read()
    demo.ParseFromString(data)
    print(demo)
    print('-' *  30)
    # 反序列化 json 数据
    data = open('data.json', 'r').read()
    demo = json_format.Parse(data, Demo())
    print(demo)
if __name__ == '__main__':
    test01()
    test02()
    test03()

 冀公网安备13050302001966号
 冀公网安备13050302001966号