Python中使用Protocol Buffers进行数据序列化的完整指南
本文详细解析Python中使用Google Protocol Buffers(Protobuf)进行数据序列化的过程。内容涵盖Protobuf与XML、JSON的对比,其高传输效率、跨平台兼容性及二进制存储优缺点。通过具体的.proto定义示例和Python代码,演示如何构建消息、序列化与反序列化数据,适用于需要高效网络通信的场景。
概念
Protobuf(Google Protocol Buffers)是Google开发的一套用于数据存储和网络通信协议编解码的工具库。它的作用类似于XML和JSON,即将数据以特定格式保存。与XML和JSON不同,Protobuf采用二进制数据格式,因此在传输、打包和解包效率上具有显著优势。
优点:
1:序列化后的数据体积相比JSON和XML更小,非常适合网络传输场景。
2:支持跨平台和多语言开发。
3:消息格式升级时具备良好的兼容性。
4:序列化和反序列化速度非常快,处理效率高于JSON。
缺点:
1、数据以二进制方式存储,如果没有对应的.proto定义文件,无法直接读取Protobuf的内容。
2、功能相对简单,不适合表示极其复杂的概念结构。
标准数据类型
标量消息字段可以包含多种类型,下表展示了在.proto文件中定义的类型,以及自动生成的访问类中对应的类型。

基于序号的协议字段映射(类似key-value结构)
新建 test.proto
在消息中,承载的数据对应于每一个字段,每个字段都拥有名字和类型。
syntax = "proto3";
package WeightEstimationUpdate;
option java_package = "com.muyuan.platform.bar.patrol.pro";
// 请求包基类(没有附加数据,通信包不重新定义直接使用基类包)
message BaseRequestCommon
{
string DeviceId = 1; // 设备编号
string MsgID = 2; // 消息ID,用UUID
string Timestamp = 3; // unix时间戳(秒)
uint32 Cmd = 4; // 指令信息
bytes payLoad = 5; // 消息体
}
// 上报
message DeviceRegist
{
string version = 1; //
string macAddr = 2; //
}
// 下发
message PushUpgradeInfo
{
string version = 1; // 版本号
string packageName = 2; //
string packageMd5 = 3; //
string packageUrl = 4; //
}
// 上报
message ReportWeightEstimationStatus
{
string version = 1; //
string state = 2; //
}
// 指令列表
enum EmCmd
{
CMD_NONE = 0x0000; // 指令开始范围
//-----------------服务器端主动下发到设备端信令定义开始------------------
CMD_S2C_PUSH_UPGRADE_INFO = 0x0013; // 下发(协议包:PushUpgradeInfo)
//-----------------服务器端主动下发到设备端信令定义结束-----------------
//-----------------设备端主动上报到服务端信令定义开始-------------------
CMD_C2S_REPORT_REGIST = 0x0060; // 注册(协议包:WeightEstimationRegist)
CMD_C2S_REPORT_FAULT = 0x0061; // 上报故障(协议包:ReportFault)
CMD_C2S_REPORT_WEIGHT_ESTIMATION_STATUS = 0x0063; // 上报状态信息(协议包:WeightEstimationStatus)
//-----------------设备端主动上报到服务端信令定义结束-----------------
CMD_END = 0xFFFF; // 指令结束范围
}
情况1: 收到通信信息
import test_pb2 as weight_pd
base_request_common_obj = weight_pd.BaseRequestCommon()
base_request_common_obj.ParseFromString(msg)
payload = base_request_common_obj.payLoad
push_upgrade_info_obj = weight_pd.PushUpgradeInfo()
push_upgrade_info_obj.ParseFromString(payload)
update_version = push_upgrade_info_obj.version
update_zip_filename = push_upgrade_info_obj.packageName
# 反向解析即可
情况2:发送通信信息
import test_pb2 as weight_pd
base_request_common = weight_pd.BaseRequestCommon()
base_request_common.DeviceId = deviceId
base_request_common.MsgID = str(uuid.uuid4())
base_request_common.Timestamp = str(int(time.time()))
# change
item_list = weight_pd.EmCmd.items()
#此为 protobuf 3.0.0 版本的
weight_dict = listtuple_dict(item_list)
base_request_common.Cmd = weight_dict.get("CMD_C2S_REPORT_WEIGHT_ESTIMATION_STATUS")
#此为 protobuf 最新版本
# base_request_common.Cmd = weight_pd.EmCmd.CMD_C2S_REPORT_WEIGHT_ESTIMATION_STATUS
report_weight_estimation_status = weight_pd.ReportWeightEstimationStatus()
report_weight_estimation_status.version = self.version
report_weight_estimation_status.state = state
base_request_common.payLoad = report_weight_estimation_status.SerializeToString()
serializeToString = base_request_common.SerializeToString()
# serializeToString 即为 二进制数据流
def listtuple_dict(item_list):
weight_cmd_dict = {}
for k, v in item_list:
weight_cmd_dict.setdefault(k, v)
return weight_cmd_dict```
到此这篇关于python使用protobuf的文章就介绍到这了,更多相关python使用protobuf内容请搜索本站以前的文章或继续浏览下面的相关文章希望大家以后多多支持本站!
免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。









