python操作protobuf基础

概要

Protobuf是一种数据格式,它支持跨语言,它有以下好处:

  • 它是按照二进制方式进行存储,同时数据协议提前定义好(这样不需要存储key),默认值字段不进行传输,因此压缩效率很高;
  • 即使数据格式发生演进,protobuf也能很方便做到向后兼容(通过序列号);
  • 被grpc集成;

本文主要通过一个示例介绍python操作protobuf的流程和关键字

示例

两个proto文件

person.proto

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
}

person_info.proto

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:表示该字段必填

每个字段后都跟随一个数字,当结构体演进时数字和字段的关系保持不变。这样老版本的代码也可以读取新版本的数据,反之依然。

生成proto文件对应的python代码

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进行赋值

dump文件

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.

你可能感兴趣的:(python,protobuf)