开发学院

您的位置:首页>教程>正文

教程正文

Protocol Buffer Python实例教程:Protocol Buffer API

  与生成Java和C++的Protocol Buffer代码不同,Python的Protocol Buffer编译器不会直接为您生成数据访问代码。取而代之的是(如您在addressbook_pb2.py中看到的),它为您的所有消息、枚举和字段以及一些神秘的空类生成特殊的描述符,每种消息对应一个类型:

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

  每个类中的重要一行是__metaclass__ = reflection.GeneratedProtocolMessageType。虽然Python元类如何工作的细节超出了本教程的范围,但您可以将其视为创建类的模板。在加载时,GeneratedProtocolMessageType元类使用指定的描述符来创建处理每种消息类型所需的所有Python方法,并将它们添加到相关的类中。然后,您可以在代码中使用完全填充的类。

  所有这些的最终效果是,您可以使用Person类,就像它将消息基类的每个字段定义为常规字段一样。例如,你可以写:

import addressbook_pb2
person = addressbook_pb2.Person()
person.id = 1234
person.name = "John Doe"
person.email = "jdoe@example.com"
phone = person.phones.add()
phone.number = "555-4321"
phone.type = addressbook_pb2.Person.HOME.

  请注意,这些分配不仅仅是向通用Python对象添加任意新字段。如果您试图分配.proto文件中未定义的字段,将会引发属性错误(AttributeError)。如果将字段分配给错误类型的值,将引发类型错误。此外,在设置字段之前读取字段值会返回默认值。

person.no_such_field = 1  # raises AttributeError
person.id = "1234"        # raises TypeError

  有关协议编译器为任何特定字段定义生成的确切成员的更多信息,请参见Python生成的代码引用。

枚举

元类将枚举扩展成一组具有整数值的符号常量。例如,常数addressbook_pb2.Person.WORK 的值为 2。

标准消息方法

  每个消息类还包含许多其他方法,可以让您检查或摆布整个消息,包括:

  IsInitialized(): 检查是否所有必填字段都已设置。

  __str__(): 返回人类可读的消息,对调试特别有用。(通常作为字符串(消息)或打印消息调用。)

  CopyFrom(other_msg): 用给定消息的值覆盖消息

  Clear(): 将所有元素清除回空状态。

  这些方法实现了消息接口。有关更多信息,请参见完整的消息应用编程接口文档。

解析和序列化

  最后,每个类都有使用protocol buffer二进制格式写入和读取所选类型消息的方法。其中包括:

  SerializeToString(): 序列化消息并将其作为字符串返回。请注意,字节是二进制的,不是文本;我们只使用str类型作为方便的容器。

  ParseFromString(data): 解析给定字符串中的消息。

  这些只是为解析和序列化提供的几个选项。同样,有关完整列表,请参见消息应用编程接口参考。