Protobuf是一种数据格式,它支持跨语言,它有以下好处:
本文主要通过一个示例介绍python操作protobuf的流程和关键字
syntax = "proto2";
import "person_info.proto";
package persons;
message Person {
optional PersonInfo info = 1; // characteristics of the person
repeated Friend friends = 2; // friends of the person
}
message Friend {
optional float friendship_duration = 1; // duration of friendship in days
repeated string shared_hobbies = 2; // shared interests
optional Person person = 3; // identity of the friend
}
syntax = "proto2";
package persons;
enum Sex {
M = 0; // male
F = 1; // female
O = 2; // other
}
message PersonInfo {
optional int32 age = 1; // age in years
optional Sex sex = 2;
optional int32 height = 3; // height in cm
}
Syntax:proto2或者proto3,是protobuf的两个版本
Import:以来别的proto文件
Package:定义的namespace空间
Enum:定义枚举类型
Messsage:类似c语言中的struct,表示结构体
Repeated:表示该字段为数组
Optional:表示该字段可以不填
Required:表示该字段必填
每个字段后都跟随一个数字,当结构体演进时数字和字段的关系保持不变。这样老版本的代码也可以读取新版本的数据,反之依然。
protoc ./interfaces/person_info.proto --python_out generated/
protoc ./interfaces/person.proto --python_out generated/
import person_pb2
import person_info_pb2
############
# define friend for person of interest
#############
friend_info = person_info_pb2.PersonInfo()
friend_info.age = 40
friend_info.sex = person_info_pb2.Sex.M
friend_info.height = 165
friend_person = person_pb2.Person()
friend_person.info.CopyFrom(friend_info)
friend_person.friends.extend([]) # no friends :-(
#######
# define friendship characteristics
########
friendship = person_pb2.Friend()
friendship.friendship_duration = 365.1
friendship.shared_hobbies.extend(["books", "daydreaming", "unicorns"])
friendship.person.CopyFrom(friend_person)
#######
# assign the friend to the friend of interest
#########
person_info = person_info_pb2.PersonInfo()
person_info.age = 30
person_info.sex = person_info_pb2.Sex.M
person_info.height = 184
person = person_pb2.Person()
person.info.CopyFrom(person_info)
person.friends.extend([friendship]) # person with a single friend
对于简单类型(数字,字符串,布尔),可以通过‘=’直接赋值
对于repeated字段,通过extend进行赋值
对于内嵌的message字段,通过CopyFrom进行赋值
import os
out_dir = "proto_dump"
with open(os.path.join(out_dir, "person.pb"), "wb") as f:
# binary output
f.write(person.SerializeToString())
with open(os.path.join(out_dir, "person.protobuf"), "w") as f:
# human-readable output for debugging
f.write(str(person))
一个是二进制格式,另一个是有可读性的json格式。我们可以看到二进制格式的文件其文件大小是另一个文件的1/5.