Python中应用protobuf的示例详解

  • Post category:Python

Python中应用protobuf的示例详解

Protobuf是一种轻量级,高性能,语言无关的序列化框架,用于数据交换和存储。本文将介绍如何在Python中使用protobuf。

安装protobuf

在使用protobuf之前,需要先安装protobuf库:

pip install protobuf

编写proto文件

protobuf使用.proto文件定义交换的消息格式。例如,以下是定义一个简单消息格式的.proto文件的示例:

syntax = "proto3";

message Person {
  string name = 1;
  int32 age = 2;
}

上述.proto文件定义了一个消息格式,名为Person,包含两个字段:name和age。其中,name的类型为字符串,字段编号为1;age的类型为32位整型数,字段编号为2。

生成Python代码

使用protoc命令可以将.proto文件编译为各种编程语言的代码。例如,以下命令将生成Python代码:

protoc --python_out=. person.proto

编译后将生成person_pb2.py文件,其中包含Person消息的Python类。

序列化和反序列化

在Python中使用protobuf,可以通过Person类序列化和反序列化消息。以下是示例代码:

import person_pb2

# 创建Person实例
person = person_pb2.Person()
person.name = 'Alice'
person.age = 20

# 将Person序列化为字节串
bytes = person.SerializeToString()

# 将字节串反序列化为Person实例
new_person = person_pb2.Person()
new_person.ParseFromString(bytes)

# 打印反序列化后的Person实例
print(new_person)

上述代码中,首先创建一个Person实例,然后将其序列化为字节串。接着,通过ParseFromString方法将字节串反序列化为Person实例,最后将反序列化后的Person实例打印出来。

示例1:嵌套消息

除了简单的字段,protobuf还支持嵌套消息的定义。以下是一个示例的.proto文件:

syntax = "proto3";

message Phone {
  string number = 1;
  int32 type = 2;
}

message Person {
  string name = 1;
  int32 age = 2;
  repeated Phone phones = 3;
}

.phone表示电话号码,.person表示人名,其中.phone信息还嵌套在了.person信息里。以下是该.proto文件编译生成的Python代码:

# Phone类定义
class Phone(proto.Message):
    number = proto.Field(proto.STRING, number=1)
    type = proto.Field(proto.INT32, number=2)


# Person类定义
class Person(proto.Message):
    name = proto.Field(proto.STRING, number=1)
    age = proto.Field(proto.INT32, number=2)
    phones = proto.RepeatedField(Phone, number=3)

上述代码中,Proto文件中定义了嵌套的消息结构,生成的Python代码中使用嵌套的Python类表示这个结构。

以下是创建和序列化一个包含phone信息的Person实例的示例代码:

import person_pb2

# 创建Person实例
person = person_pb2.Person()
person.name = 'Bob'
person.age = 30

# 添加Phone信息
phone = person.phones.add()
phone.number = '123456789'
phone.type = 1

# 将Person实例序列化为字节串
bytes = person.SerializeToString()

# 将字节串反序列化为Person实例
new_person = person_pb2.Person()
new_person.ParseFromString(bytes)

# 打印反序列化后的Person实例
print(new_person)

上述示例中,首先创建一个Person实例,然后添加一个Phone信息到phones中,最后将Person实例序列化为字节串,再反序列化为新的Person实例,并将其打印出来。

示例2:使用Python字典构建消息

在实际使用中,有时需要根据现有信息创建一个Protobuf消息对象。可以使用Python字典来构建一个消息。以下是一个使用字典构建消息的示例:

import person_pb2

person_dict = {
    'name': 'Tom',
    'age': 40,
    'phones': [
        {'number': '987654321', 'type': 2},
        {'number': '012345678', 'type': 1},
    ]
}

# 使用字典构建Person实例
person = person_pb2.Person()
person.ParseFromDict(person_dict)

# 将Person实例序列化为字节串
bytes = person.SerializeToString()

# 将字节串反序列化为Person实例
new_person = person_pb2.Person()
new_person.ParseFromString(bytes)

# 打印反序列化后的Person实例
print(new_person)

上述示例中,首先创建一个字典person_dict,包含了Person实例的各个字段信息和Phone信息。然后使用ParseFromDict方法将字典转换为Person实例,最后将Person实例序列化为字节串并反序列化为新的Person实例。