Protocol Buffers(简称ProtoBuf)是Google公司开发的一种与语言和平台无关的、可扩展的、序列化结构数据的方法,可用于(数据)通信协议、数据存储等。用户可以利用ProtoBuf定义数据的结构,然后使用特殊生成的源代码轻松地在各种数据流中使用各种语言来编写和读取结构数据,甚至还可以在不破坏由旧数据结构编译的已部署程序的基础上更新数据结构。ProtoBuf目前有两个版本,分别是proto2和proto3,其中最新版本的proto3提供了对C++、Java、Python、Object-C、C#、Ruby、Go、PHP、Dart、Javascript等多种语言的支持。
ProtoBuf开源地址:https://github.com/protocolbuffers/protobuf
主流序列化协议:json、xml、ProtoBuf。
ProtoBuf通常应用于在网络通信和通用数据交换等应用场景中。包括:
跨平台的RPC数据传输;
相比json的解析要更快、数据量更小,而且数据结构明朗的数据传输或存储。
在一个需要大量的数据传输的场景中,如果数据量很大,那么选择ProtoBuf可以明显的减少数据量,减少网络IO,从而减少网络传输所消耗的时间 。
下载protoc https://github.com/protocolbuffers/protobuf/releases
根据自己的平台下载对应的可执行二进制包,也可以下载源码包自行编译。
以windows为例,解压可以在解压缩后的bin目录下看到protoc.exe文件,执行protoc.exec --version
可以查看版本号。
如果想在本机任意路径下执行protoc命令,需要将该bin路径添加到系统环境变量中。(右键我的电脑 -> 高级系统设置 -> 高级 -> 环境变量 -> Path -> 编辑 -> 新建 )
新建python项目proto-test,新建文件夹protobuf,在该文件夹下新建addressbook.proto文件,内容如下:
syntax = 'proto3';
message Person {
string name = 1;
int32 id = 2;
string email = 3;
enum PhoneType {
MOBILE = 0;
HOME = 1;
WORK = 2;
}
message PhoneNumber {
string number = 1;
PhoneType type = 2;
}
repeated PhoneNumber phones = 4;
}
message AddressBook {
repeated Person people = 1;
}
使用protoc编译器将生成python所需的pb文件
protoc --python_out=./ addressbool.proto
在protobuf文件夹下生成addressbook_pb2.py
执行pip install protobuf
,安装依赖。
新建address_test_writing.py测试序列化,将序列化后的数据写入data/addressboo.txt中。
address_test.writing.py的内容如下:
from protobuf import addressbook_pb2
def PromptForAddress(person):
person.id = 1
person.name = "myname"
person.email = "[email protected]"
phone_number = person.phones.add()
phone_number.number = "123456789"
phone_number.type = addressbook_pb2.Person.MOBILE
def write_test():
address_book = addressbook_pb2.AddressBook()
address_book_file = "./data/addressbook.txt"
try:
f = open(address_book_file, "rb")
address_book.ParseFromString(f.read())
f.close()
except IOError:
print(address_book_file + ": Could not open file. Creating a new one.")
PromptForAddress(address_book.people.add())
f = open(address_book_file, "wb")
f.write(address_book.SerializeToString()) # 将对象序列化为二进制字符串
print(address_book.SerializeToString())
f.close()
if __name__ == "__main__":
write_test()
新建address_test_reading.py测试反序列化。
address_test_reading.py的内容如下:
import protobuf.addressbook_pb2 as addressbook_pb2
def ListPeople(address_book):
for person in address_book.people:
print("Person ID:", person.id)
print(" Name:", person.name)
print(" E-mail address:", person.email)
for phone_number in person.phones:
if phone_number.type == addressbook_pb2.Person.MOBILE:
print(" Mobile phone #: ")
elif phone_number.type == addressbook_pb2.Person.HOME:
print(" Home phone #: ")
elif phone_number.type == addressbook_pb2.Person.WORK:
print(" Work phone #: ")
print(phone_number.number)
def read_test():
address_book = addressbook_pb2.AddressBook()
address_book_file = "./data/addressbook.txt"
f = open(address_book_file, "rb")
address_book.ParseFromString(f.read()) # 解析一个二进制字符串
print(type(address_book))
f.close()
ListPeople(address_book)
if __name__ == "__main__":
read_test()
总一下Python3使用ProtoBuf目录结构如下:
参考:
https://github.com/protocolbuffers/protobuf
Protobuf 安装使用入门教程
Python3-如何使用protobuf 3(图文详解)
Protobuf之proto基础语法
ProtoBuf介绍及应用