#! /usr/bin/python
import addressbook_pb2
import sys
# This function fills in a Person message based on user input.
def PromptForAddress(person):
person.id = int(raw_input("Enter person ID number: "))
person.name = raw_input("Enter name: ")
email = raw_input("Enter email address (blank for none): ")
if email != "":
person.email = email
while True:
number = raw_input("Enter a phone number (or leave blank to finish): ")
if number == "":
break
phone_number = person.phones.add()
phone_number.number = number
type = raw_input("Is this a mobile, home, or work phone? ")
if type == "mobile":
phone_number.type = addressbook_pb2.Person.PhoneType.MOBILE
elif type == "home":
phone_number.type = addressbook_pb2.Person.PhoneType.HOME
elif type == "work":
phone_number.type = addressbook_pb2.Person.PhoneType.WORK
else:
print "Unknown phone type; leaving as default value."
# Main procedure: Reads the entire address book from a file,
# adds one person based on user input, then writes it back out to the same
# file.
if len(sys.argv) != 2:
print "Usage:", sys.argv[0], "ADDRESS_BOOK_FILE"
sys.exit(-1)
address_book = addressbook_pb2.AddressBook()
# Read the existing address book.
try:
f = open(sys.argv[1], "rb")
address_book.ParseFromString(f.read())
f.close()
except IOError:
print sys.argv[1] + ": Could not open file. Creating a new one."
# Add an address.
PromptForAddress(address_book.people.add())
# Write the new address book back to disk.
f = open(sys.argv[1], "wb")
f.write(address_book.SerializeToString())
f.close()
扩展协议缓冲区
在发布使用协议缓冲区的代码后早晚,您无疑会想要“改进”协议缓冲区的定义。如果您希望新的缓冲区向后兼容,而旧的缓冲区向后兼容,而您几乎肯定希望这样做,那么您需要遵循一些规则。在新版本的协议缓冲区中:
您不得更改任何现有字段的标签号。
您不得添加或删除任何必填字段。
您可以删除可选字段或重复字段。
您可以添加新的可选或重复字段,但必须使用新的标签号(即,该协议缓冲区中从未使用过的标签号,甚至删除的字段也从未使用过)。
(这些规则有一些例外,但很少使用。)
如果遵循这些规则,旧代码将愉快地读取新消息,而忽略任何新字段。对于旧代码,已删除的可选字段将仅具有其默认值,而删除的重复字段将为空。新代码还将透明地读取旧消息。但是,请记住,新的可选字段将不会出现在旧消息中,因此您需要明确检查是否已使用设置了这些字段,或者需要使用来has_在.proto文件中提供合理的默认值[default = value]标签编号之后。如果未为可选元素指定默认值,则使用特定于类型的默认值:对于字符串,默认值为空字符串。对于布尔值,默认值为false。对于数字类型,默认值为零。还要注意,如果添加了一个新的重复字段,则由于没有has_标记,因此新代码将无法分辨它是空的(由新代码)还是根本没有设置(由旧代码)。
高级用法
协议缓冲区的用途不只是简单的访问器和序列化。请务必浏览Python API参考,以了解您还可以使用它们做什么。
协议消息类提供的一项关键功能是反射。您可以遍历消息的字段并操纵它们的值,而无需针对任何特定的消息类型编写代码。使用反射的一种非常有用的方法是将协议消息与其他编码(例如XML或JSON)相互转换。反射的一种更高级的用法可能是查找同一类型的两条消息之间的差异,或者开发一种“协议消息的正则表达式”,在其中您可以编写与某些消息内容匹配的表达式。如果您发挥自己的想象力,可以将协议缓冲区应用于比最初预期的范围更广的问题!
源:https://developers.google.com/protocol-buffers/docs/pythontutorial