参考链接:
Protocol Buffer Basics: Python
Python Generated Code
Protocol Buffers Python API Reference
.proto
文件域名 + {} = 一个完整的域,例如:
message 域名 {
...
}
message是标志符
定义域时不需要修饰符,调用域类型(field type)时才需要
IsInitialized()
:检查是否所有required域是否设定__str__()
:输出人类可读的message,多用于debug。调用方式:str(message) / print messageCopyFrom(other_msg)
:重写messageClear()
:清除所有信息至空状态proto文件addressbook.proto
内容定义如下:
syntax = "proto2"; //proto版本申明语句
package tutorial; // package申明,防止不同项目中的同名冲突,不会对代码产生影响
message Person {
optional string name = 1;
optional int32 id = 2;
optional string email = 3;
enum PhoneType {
// 定义了一个enum类型,存储预设定的值
MOBILE = 0;
HOME = 1;
WORK = 2;
}
message PhoneNumber {
optional string number = 1;
optional PhoneType type = 2 [default = HOME]; // 使用enum
}
repeated PhoneNumber phones = 4;
}
message AddressBook {
repeated Person people = 1;
}
该文件定义了三个message数据结构,主message是AddressBook,其他message都是围绕该message展开;AddressBook带一个可重复的(repeated)Person结构(Person)的实例(people)。每个message是一个独立且隔离的域,因此在每个域中每个变量的编号是从1开始。
考虑到一个字节(byte,8bit)可以表示0-15十六个数和计算机存储的空间局部性,推荐将经常使用的变量编码为较小的值以提高效率。
编译前要先安装编译器:Download Protocol Buffers
编译命令:
protoc -I=/proto/file/folder/path --python_out=/compiled/saving/path /proto/file/path
编译xxx.proto
文件后生成proto_pb2.py
文件,直接在python导入生成的py文件即可
python protocol buffer编译器并不直接生成获取数据的代码,而是生成一个特殊的描述器来描述.proto
中定义的所有数据结构:
class Person(message.Message):
__metaclass__ = reflection.GeneratedProtocolMessageType # 重要代码
class PhoneNumber(message.Message):
__metaclass__ = reflection.GeneratedProtocolMessageType
DESCRIPTOR = _PERSON_PHONENUMBER
DESCRIPTOR = _PERSON
class AddressBook(message.Message):
__metaclass__ = reflection.GeneratedProtocolMessageType
DESCRIPTOR = _ADDRESSBOOK
可以将这些代码看做一个创建类的模板,在加载时,通过GeneratedProtocolMessageType
元类来调用特殊描述器来创建所有proto定义内容的python方法。
import addressbook_pb2 # 导入编译好的py文件
person_1 = addressbook_pb2.Person() # 申请一个Person实例
person_1.id = 123 # 赋值
person_1.name = "Dady"
person_1.email = "[email protected]"
phone_1 = person.phones.add() # 对于repeated类数据,使用add()来新增实例
phone_2 = person.phones.add()
phone_1.number = "123-456-789"
phone.type = addressbook_pb2.Person.Home
在接收到一个message后,直接调用即可
import addressbook_pb2
# 假定接收到了一个address_book message,且address_book包含多个人
for person in address_book.people:
person_id = person.id
person_name = person.name
print(person_id, person_name)