Hướng dẫn văn bản python

GHI CHÚ. Trang web này không được dùng nữa. Trang web sẽ ngừng hoạt động sau ngày 31 tháng 1 năm 2023 và lưu lượng truy cập sẽ chuyển hướng đến trang web mới tại https. // protobuf. nhà phát triển. Trong thời gian chờ đợi, các bản cập nhật sẽ chỉ được thực hiện cho protobuf. nhà phát triển

  • Nhà
  • Các sản phẩm
  • Bộ đệm giao thức
  • hướng dẫn

Thông tin cơ bản về bộ đệm giao thức. Python Sắp xếp ngăn nắp với các bộ sưu tập Lưu và phân loại nội dung dựa trên sở thích của bạn

Hướng dẫn này cung cấp phần giới thiệu cơ bản của lập trình viên Python về cách làm việc với bộ đệm giao thức. Bằng cách đi qua việc tạo một ứng dụng ví dụ đơn giản, nó chỉ cho bạn cách

  • Xác định định dạng tin nhắn trong tệp .proto
  • Sử dụng trình biên dịch bộ đệm giao thức
  • Sử dụng API bộ đệm giao thức Python để viết và đọc tin nhắn

Đây không phải là hướng dẫn toàn diện về cách sử dụng bộ đệm giao thức trong Python. Để biết thông tin tham khảo chi tiết hơn, hãy xem Hướng dẫn ngôn ngữ bộ đệm giao thức (proto2), Hướng dẫn ngôn ngữ bộ đệm giao thức (proto3), Tham chiếu API Python, Hướng dẫn mã được tạo bằng Python và Tham chiếu mã hóa

Miền vấn đề

Ví dụ chúng ta sẽ sử dụng là một ứng dụng "sổ địa chỉ" rất đơn giản có thể đọc và ghi chi tiết liên hệ của mọi người vào và từ một tệp. Mỗi người trong sổ địa chỉ đều có tên, ID, địa chỉ email và số điện thoại liên hệ

Làm cách nào để bạn tuần tự hóa và truy xuất dữ liệu có cấu trúc như thế này?

  • Sử dụng Python ngâm. Đây là cách tiếp cận mặc định vì nó được tích hợp vào ngôn ngữ, nhưng nó không xử lý tốt quá trình phát triển lược đồ và cũng không hoạt động tốt nếu bạn cần chia sẻ dữ liệu với các ứng dụng được viết bằng C++ hoặc Java
  • Bạn có thể phát minh ra một cách đặc biệt để mã hóa các mục dữ liệu thành một chuỗi duy nhất – chẳng hạn như mã hóa 4 số nguyên là "12. 3. -23. 67". Đây là một cách tiếp cận đơn giản và linh hoạt, mặc dù nó yêu cầu viết mã mã hóa và phân tích cú pháp một lần và việc phân tích cú pháp áp đặt một chi phí thời gian chạy nhỏ. Điều này hoạt động tốt nhất để mã hóa dữ liệu rất đơn giản
  • Tuần tự hóa dữ liệu thành XML. Cách tiếp cận này có thể rất hấp dẫn vì XML (gần như) con người có thể đọc được và có các thư viện ràng buộc cho nhiều ngôn ngữ. Đây có thể là một lựa chọn tốt nếu bạn muốn chia sẻ dữ liệu với các ứng dụng/dự án khác. Tuy nhiên, XML nổi tiếng là sử dụng nhiều không gian và việc mã hóa/giải mã nó có thể áp đặt một hình phạt hiệu suất rất lớn đối với các ứng dụng. Ngoài ra, việc điều hướng một cây XML DOM phức tạp hơn nhiều so với việc điều hướng các trường đơn giản trong một lớp thông thường.

Thay vì các tùy chọn này, bạn có thể sử dụng bộ đệm giao thức. Bộ đệm giao thức là giải pháp linh hoạt, hiệu quả, tự động để giải quyết chính xác vấn đề này. Với bộ đệm giao thức, bạn viết mô tả .proto về cấu trúc dữ liệu mà bạn muốn lưu trữ. Từ đó, trình biên dịch bộ đệm giao thức tạo ra một lớp thực hiện mã hóa và phân tích cú pháp tự động dữ liệu bộ đệm giao thức với định dạng nhị phân hiệu quả. Lớp được tạo cung cấp getters và setters cho các trường tạo nên bộ đệm giao thức và đảm nhiệm các chi tiết về đọc và ghi bộ đệm giao thức dưới dạng một đơn vị. Điều quan trọng là định dạng bộ đệm giao thức hỗ trợ ý tưởng mở rộng định dạng theo thời gian sao cho mã vẫn có thể đọc dữ liệu được mã hóa bằng định dạng cũ

Nơi tìm mã ví dụ

Mã ví dụ được bao gồm trong gói mã nguồn, trong thư mục "ví dụ". Tải về tại đây

Xác định định dạng giao thức của bạn

Để tạo ứng dụng sổ địa chỉ, bạn cần bắt đầu với tệp .proto. Các định nghĩa trong tệp .proto rất đơn giản. bạn thêm một thông báo cho từng cấu trúc dữ liệu mà bạn muốn sắp xếp theo thứ tự, sau đó chỉ định tên và loại cho từng trường trong thông báo. Đây là tệp .proto xác định thông điệp của bạn,

protoc -I=$SRC_DIR --python_out=$DST_DIR $SRC_DIR/addressbook.proto
2

syntax = "proto2";

package tutorial;

message Person {
  optional string name = 1;
  optional int32 id = 2;
  optional string email = 3;

  enum PhoneType {
    MOBILE = 0;
    HOME = 1;
    WORK = 2;
  }

  message PhoneNumber {
    optional string number = 1;
    optional PhoneType type = 2 [default = HOME];
  }

  repeated PhoneNumber phones = 4;
}

message AddressBook {
  repeated Person people = 1;
}

Như bạn có thể thấy, cú pháp tương tự như C++ hoặc Java. Hãy xem qua từng phần của tệp và xem nó làm gì

Tệp .proto bắt đầu bằng một khai báo gói, giúp tránh xung đột đặt tên giữa các dự án khác nhau. Trong Python, các gói thường được xác định theo cấu trúc thư mục, do đó, ___________4 bạn xác định trong tệp ____60_______ của mình sẽ không ảnh hưởng đến mã được tạo. Tuy nhiên, bạn vẫn nên khai báo một tên để tránh xung đột tên trong không gian tên Bộ đệm giao thức cũng như trong các ngôn ngữ không phải Python

Tiếp theo, bạn có định nghĩa tin nhắn của mình. Một tin nhắn chỉ là một tổng hợp chứa một tập hợp các trường đã nhập. Nhiều kiểu dữ liệu đơn giản tiêu chuẩn có sẵn dưới dạng các kiểu trường, bao gồm

protoc -I=$SRC_DIR --python_out=$DST_DIR $SRC_DIR/addressbook.proto
6,
protoc -I=$SRC_DIR --python_out=$DST_DIR $SRC_DIR/addressbook.proto
7,
protoc -I=$SRC_DIR --python_out=$DST_DIR $SRC_DIR/addressbook.proto
8,
protoc -I=$SRC_DIR --python_out=$DST_DIR $SRC_DIR/addressbook.proto
9 và
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
0. Bạn cũng có thể thêm cấu trúc khác vào thư của mình bằng cách sử dụng các loại thư khác làm loại trường – trong ví dụ trên, thư
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
1 chứa
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
2 thư, trong khi thư
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
3 chứa
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
1 thư. Bạn thậm chí có thể xác định các loại thư được lồng bên trong các thư khác – như bạn có thể thấy, loại
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
2 được xác định bên trong
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
1. Bạn cũng có thể xác định các loại
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
7 nếu bạn muốn một trong các trường của mình có một trong các danh sách giá trị được xác định trước – ở đây bạn muốn chỉ định rằng một số điện thoại có thể là một trong các loại điện thoại sau.
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
8,
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
9, hoặc
import addressbook_pb2
person = addressbook_pb2.Person()
person.id = 1234
person.name = "John Doe"
person.email = "[email protected]"
phone = person.phones.add()
phone.number = "555-4321"
phone.type = addressbook_pb2.Person.HOME
0

Các dấu "= 1", "= 2" trên mỗi phần tử xác định "thẻ" duy nhất mà trường đó sử dụng trong mã hóa nhị phân. Số thẻ 1-15 yêu cầu ít byte hơn để mã hóa so với số cao hơn, do đó, để tối ưu hóa, bạn có thể quyết định sử dụng các thẻ đó cho các phần tử thường được sử dụng hoặc lặp lại, để lại các thẻ 16 trở lên cho các phần tử tùy chọn ít được sử dụng hơn. Mỗi phần tử trong một trường lặp lại yêu cầu mã hóa lại số thẻ, vì vậy các trường lặp lại là những ứng cử viên đặc biệt tốt cho việc tối ưu hóa này

Mỗi trường phải được chú thích bằng một trong các công cụ sửa đổi sau

  • import addressbook_pb2
    person = addressbook_pb2.Person()
    person.id = 1234
    person.name = "John Doe"
    person.email = "[email protected]"
    phone = person.phones.add()
    phone.number = "555-4321"
    phone.type = addressbook_pb2.Person.HOME
    
    1. trường có thể hoặc không thể được đặt. Nếu giá trị trường tùy chọn không được đặt, giá trị mặc định sẽ được sử dụng. Đối với các loại đơn giản, bạn có thể chỉ định giá trị mặc định của riêng mình, như chúng tôi đã thực hiện cho số điện thoại
    import addressbook_pb2
    person = addressbook_pb2.Person()
    person.id = 1234
    person.name = "John Doe"
    person.email = "[email protected]"
    phone = person.phones.add()
    phone.number = "555-4321"
    phone.type = addressbook_pb2.Person.HOME
    
    2 trong ví dụ. Mặt khác, mặc định hệ thống được sử dụng. số không cho các loại số, chuỗi rỗng cho chuỗi, sai cho bool. Đối với thư nhúng, giá trị mặc định luôn là "phiên bản mặc định" hoặc "nguyên mẫu" của thư, không có trường nào được đặt. Gọi bộ truy cập để lấy giá trị của trường tùy chọn (hoặc bắt buộc) chưa được đặt rõ ràng luôn trả về giá trị mặc định của trường đó
  • import addressbook_pb2
    person = addressbook_pb2.Person()
    person.id = 1234
    person.name = "John Doe"
    person.email = "[email protected]"
    phone = person.phones.add()
    phone.number = "555-4321"
    phone.type = addressbook_pb2.Person.HOME
    
    3. trường có thể được lặp lại bất kỳ số lần nào (bao gồm cả số 0). Thứ tự của các giá trị lặp lại sẽ được giữ nguyên trong bộ đệm giao thức. Hãy nghĩ về các trường lặp lại dưới dạng các mảng có kích thước động
  • import addressbook_pb2
    person = addressbook_pb2.Person()
    person.id = 1234
    person.name = "John Doe"
    person.email = "[email protected]"
    phone = person.phones.add()
    phone.number = "555-4321"
    phone.type = addressbook_pb2.Person.HOME
    
    4. một giá trị cho trường phải được cung cấp, nếu không, thông báo sẽ được coi là "chưa được khởi tạo". Nối tiếp một tin nhắn chưa được khởi tạo sẽ đưa ra một ngoại lệ. Phân tích cú pháp một tin nhắn chưa được khởi tạo sẽ không thành công. Khác với điều này, một trường bắt buộc hoạt động chính xác như một trường tùy chọn

Bắt buộc là Mãi mãi Bạn nên rất cẩn thận khi đánh dấu các trường là

import addressbook_pb2
person = addressbook_pb2.Person()
person.id = 1234
person.name = "John Doe"
person.email = "[email protected]"
phone = person.phones.add()
phone.number = "555-4321"
phone.type = addressbook_pb2.Person.HOME
4. Nếu tại một thời điểm nào đó bạn muốn dừng viết hoặc gửi trường bắt buộc, sẽ có vấn đề khi thay đổi trường này thành trường tùy chọn – người đọc cũ sẽ coi thư không có trường này là không đầy đủ và có thể vô tình từ chối hoặc loại bỏ chúng. Thay vào đó, bạn nên xem xét việc viết các quy trình xác thực tùy chỉnh dành riêng cho ứng dụng cho bộ đệm của mình. Trong Google, các trường
import addressbook_pb2
person = addressbook_pb2.Person()
person.id = 1234
person.name = "John Doe"
person.email = "[email protected]"
phone = person.phones.add()
phone.number = "555-4321"
phone.type = addressbook_pb2.Person.HOME
4 không được ưa chuộng lắm; . (Proto3 hoàn toàn không hỗ trợ các trường
import addressbook_pb2
person = addressbook_pb2.Person()
person.id = 1234
person.name = "John Doe"
person.email = "[email protected]"
phone = person.phones.add()
phone.number = "555-4321"
phone.type = addressbook_pb2.Person.HOME
4. )

Bạn sẽ tìm thấy hướng dẫn đầy đủ để viết tệp .proto – bao gồm tất cả các loại trường có thể có – trong Hướng dẫn ngôn ngữ bộ đệm giao thức. Tuy nhiên, đừng tìm kiếm các cơ sở tương tự như kế thừa lớp – bộ đệm giao thức không làm điều đó

Biên dịch bộ đệm giao thức của bạn

Bây giờ bạn đã có một .proto, điều tiếp theo bạn cần làm là tạo các lớp mà bạn sẽ cần để đọc và viết các thông báo

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
3 (và do đó là các thông báo
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
1 và
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
2). Để thực hiện việc này, bạn cần chạy trình biên dịch bộ đệm giao thức
person.no_such_field = 1  # raises AttributeError
person.id = "1234"        # raises TypeError
5 trên .proto của mình

  1. Nếu bạn chưa cài đặt trình biên dịch, hãy tải xuống gói "protoc" và làm theo hướng dẫn trong README
  2. Bây giờ hãy chạy trình biên dịch, chỉ định thư mục nguồn (nơi mã nguồn của ứng dụng của bạn tồn tại – thư mục hiện tại được sử dụng nếu bạn không cung cấp giá trị), thư mục đích (nơi bạn muốn mã được tạo; thường giống như
    person.no_such_field = 1  # raises AttributeError
    person.id = "1234"        # raises TypeError
    
    7 . Trong trường hợp này, bạn.
    protoc -I=$SRC_DIR --python_out=$DST_DIR $SRC_DIR/addressbook.proto
    Vì bạn muốn các lớp Python, bạn sử dụng tùy chọn
    person.no_such_field = 1  # raises AttributeError
    person.id = "1234"        # raises TypeError
    
    9 – các tùy chọn tương tự được cung cấp cho các ngôn ngữ được hỗ trợ khác

Điều này tạo ra

#! /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()
0 trong thư mục đích được chỉ định của bạn

API bộ đệm giao thức

Không giống như khi bạn tạo mã bộ đệm giao thức Java và C++, trình biên dịch bộ đệm giao thức Python không trực tiếp tạo mã truy cập dữ liệu cho bạn. Thay vào đó (như bạn sẽ thấy nếu bạn nhìn vào

#! /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()
0), nó tạo ra các bộ mô tả đặc biệt cho tất cả các thư, bảng liệt kê và trường của bạn và một số lớp trống bí ẩn, mỗi lớp cho một loại thư

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

Dòng quan trọng trong mỗi lớp là

#! /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()
2. Mặc dù các chi tiết về cách thức hoạt động của các siêu dữ liệu Python nằm ngoài phạm vi của hướng dẫn này, nhưng bạn có thể coi chúng giống như một khuôn mẫu để tạo các lớp. Tại thời điểm tải, siêu lớp
#! /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()
3 sử dụng các bộ mô tả đã chỉ định để tạo tất cả các phương thức Python mà bạn cần để làm việc với từng loại thông báo và thêm chúng vào các lớp có liên quan. Sau đó, bạn có thể sử dụng các lớp được điền đầy đủ trong mã của mình

Kết quả cuối cùng của tất cả những điều này là bạn có thể sử dụng lớp

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
1 như thể nó định nghĩa từng trường của lớp cơ sở
#! /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()
5 như một trường thông thường. Ví dụ, bạn có thể viết

import addressbook_pb2
person = addressbook_pb2.Person()
person.id = 1234
person.name = "John Doe"
person.email = "[email protected]"
phone = person.phones.add()
phone.number = "555-4321"
phone.type = addressbook_pb2.Person.HOME

Lưu ý rằng các nhiệm vụ này không chỉ thêm các trường mới tùy ý vào một đối tượng Python chung. Nếu bạn cố gắng chỉ định một trường không được xác định trong tệp .proto, thì sẽ xuất hiện một số

#! /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()
7. Nếu bạn chỉ định một trường cho một giá trị không đúng loại, một số
#! /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()
8 sẽ xuất hiện. Ngoài ra, việc đọc giá trị của một trường trước khi nó được đặt sẽ trả về giá trị mặc định

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

Để biết thêm thông tin về chính xác những thành phần mà trình biên dịch giao thức tạo ra cho bất kỳ định nghĩa trường cụ thể nào, hãy xem tham chiếu mã do Python tạo ra

liệt kê

Enums được siêu dữ liệu mở rộng thành một tập hợp các hằng số tượng trưng với các giá trị nguyên. Vì vậy, ví dụ, hằng số

#! /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()
9 có giá trị 2

Phương thức nhắn tin tiêu chuẩn

Mỗi lớp thông báo cũng chứa một số phương thức khác cho phép bạn kiểm tra hoặc thao tác với toàn bộ thông báo, bao gồm

  • #! /usr/bin/python
    
    import addressbook_pb2
    import sys
    
    # Iterates though all people in the AddressBook and prints info about them.
    def ListPeople(address_book):
      for person in address_book.people:
        print "Person ID:", person.id
        print "  Name:", person.name
        if person.HasField('email'):
          print "  E-mail address:", person.email
    
        for phone_number in person.phones:
          if phone_number.type == addressbook_pb2.Person.PhoneType.MOBILE:
            print "  Mobile phone #: ",
          elif phone_number.type == addressbook_pb2.Person.PhoneType.HOME:
            print "  Home phone #: ",
          elif phone_number.type == addressbook_pb2.Person.PhoneType.WORK:
            print "  Work phone #: ",
          print phone_number.number
    
    # Main procedure:  Reads the entire address book from a file and prints all
    #   the information inside.
    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.
    f = open(sys.argv[1], "rb")
    address_book.ParseFromString(f.read())
    f.close()
    
    ListPeople(address_book)
    
    0. kiểm tra xem tất cả các trường bắt buộc đã được đặt chưa
  • #! /usr/bin/python
    
    import addressbook_pb2
    import sys
    
    # Iterates though all people in the AddressBook and prints info about them.
    def ListPeople(address_book):
      for person in address_book.people:
        print "Person ID:", person.id
        print "  Name:", person.name
        if person.HasField('email'):
          print "  E-mail address:", person.email
    
        for phone_number in person.phones:
          if phone_number.type == addressbook_pb2.Person.PhoneType.MOBILE:
            print "  Mobile phone #: ",
          elif phone_number.type == addressbook_pb2.Person.PhoneType.HOME:
            print "  Home phone #: ",
          elif phone_number.type == addressbook_pb2.Person.PhoneType.WORK:
            print "  Work phone #: ",
          print phone_number.number
    
    # Main procedure:  Reads the entire address book from a file and prints all
    #   the information inside.
    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.
    f = open(sys.argv[1], "rb")
    address_book.ParseFromString(f.read())
    f.close()
    
    ListPeople(address_book)
    
    1. trả về một biểu diễn tin nhắn mà con người có thể đọc được, đặc biệt hữu ích cho việc gỡ lỗi. (Thường được gọi là
    #! /usr/bin/python
    
    import addressbook_pb2
    import sys
    
    # Iterates though all people in the AddressBook and prints info about them.
    def ListPeople(address_book):
      for person in address_book.people:
        print "Person ID:", person.id
        print "  Name:", person.name
        if person.HasField('email'):
          print "  E-mail address:", person.email
    
        for phone_number in person.phones:
          if phone_number.type == addressbook_pb2.Person.PhoneType.MOBILE:
            print "  Mobile phone #: ",
          elif phone_number.type == addressbook_pb2.Person.PhoneType.HOME:
            print "  Home phone #: ",
          elif phone_number.type == addressbook_pb2.Person.PhoneType.WORK:
            print "  Work phone #: ",
          print phone_number.number
    
    # Main procedure:  Reads the entire address book from a file and prints all
    #   the information inside.
    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.
    f = open(sys.argv[1], "rb")
    address_book.ParseFromString(f.read())
    f.close()
    
    ListPeople(address_book)
    
    2 hoặc
    #! /usr/bin/python
    
    import addressbook_pb2
    import sys
    
    # Iterates though all people in the AddressBook and prints info about them.
    def ListPeople(address_book):
      for person in address_book.people:
        print "Person ID:", person.id
        print "  Name:", person.name
        if person.HasField('email'):
          print "  E-mail address:", person.email
    
        for phone_number in person.phones:
          if phone_number.type == addressbook_pb2.Person.PhoneType.MOBILE:
            print "  Mobile phone #: ",
          elif phone_number.type == addressbook_pb2.Person.PhoneType.HOME:
            print "  Home phone #: ",
          elif phone_number.type == addressbook_pb2.Person.PhoneType.WORK:
            print "  Work phone #: ",
          print phone_number.number
    
    # Main procedure:  Reads the entire address book from a file and prints all
    #   the information inside.
    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.
    f = open(sys.argv[1], "rb")
    address_book.ParseFromString(f.read())
    f.close()
    
    ListPeople(address_book)
    
    3. )
  • #! /usr/bin/python
    
    import addressbook_pb2
    import sys
    
    # Iterates though all people in the AddressBook and prints info about them.
    def ListPeople(address_book):
      for person in address_book.people:
        print "Person ID:", person.id
        print "  Name:", person.name
        if person.HasField('email'):
          print "  E-mail address:", person.email
    
        for phone_number in person.phones:
          if phone_number.type == addressbook_pb2.Person.PhoneType.MOBILE:
            print "  Mobile phone #: ",
          elif phone_number.type == addressbook_pb2.Person.PhoneType.HOME:
            print "  Home phone #: ",
          elif phone_number.type == addressbook_pb2.Person.PhoneType.WORK:
            print "  Work phone #: ",
          print phone_number.number
    
    # Main procedure:  Reads the entire address book from a file and prints all
    #   the information inside.
    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.
    f = open(sys.argv[1], "rb")
    address_book.ParseFromString(f.read())
    f.close()
    
    ListPeople(address_book)
    
    4. ghi đè tin nhắn bằng các giá trị của tin nhắn đã cho
  • #! /usr/bin/python
    
    import addressbook_pb2
    import sys
    
    # Iterates though all people in the AddressBook and prints info about them.
    def ListPeople(address_book):
      for person in address_book.people:
        print "Person ID:", person.id
        print "  Name:", person.name
        if person.HasField('email'):
          print "  E-mail address:", person.email
    
        for phone_number in person.phones:
          if phone_number.type == addressbook_pb2.Person.PhoneType.MOBILE:
            print "  Mobile phone #: ",
          elif phone_number.type == addressbook_pb2.Person.PhoneType.HOME:
            print "  Home phone #: ",
          elif phone_number.type == addressbook_pb2.Person.PhoneType.WORK:
            print "  Work phone #: ",
          print phone_number.number
    
    # Main procedure:  Reads the entire address book from a file and prints all
    #   the information inside.
    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.
    f = open(sys.argv[1], "rb")
    address_book.ParseFromString(f.read())
    f.close()
    
    ListPeople(address_book)
    
    5. xóa tất cả các phần tử trở lại trạng thái trống

Các phương thức này triển khai giao diện

#! /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()
5. Để biết thêm thông tin, hãy xem

Phân tích cú pháp và tuần tự hóa

Cuối cùng, mỗi lớp bộ đệm giao thức có các phương thức để viết và đọc thông báo thuộc loại bạn đã chọn bằng cách sử dụng định dạng nhị phân của bộ đệm giao thức. Bao gồm các

  • #! /usr/bin/python
    
    import addressbook_pb2
    import sys
    
    # Iterates though all people in the AddressBook and prints info about them.
    def ListPeople(address_book):
      for person in address_book.people:
        print "Person ID:", person.id
        print "  Name:", person.name
        if person.HasField('email'):
          print "  E-mail address:", person.email
    
        for phone_number in person.phones:
          if phone_number.type == addressbook_pb2.Person.PhoneType.MOBILE:
            print "  Mobile phone #: ",
          elif phone_number.type == addressbook_pb2.Person.PhoneType.HOME:
            print "  Home phone #: ",
          elif phone_number.type == addressbook_pb2.Person.PhoneType.WORK:
            print "  Work phone #: ",
          print phone_number.number
    
    # Main procedure:  Reads the entire address book from a file and prints all
    #   the information inside.
    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.
    f = open(sys.argv[1], "rb")
    address_book.ParseFromString(f.read())
    f.close()
    
    ListPeople(address_book)
    
    8. tuần tự hóa tin nhắn và trả về nó dưới dạng một chuỗi. Lưu ý rằng các byte là nhị phân, không phải văn bản;
  • .proto0. phân tích cú pháp một tin nhắn từ chuỗi đã cho

Đây chỉ là một vài tùy chọn được cung cấp để phân tích cú pháp và tuần tự hóa. Một lần nữa, hãy xem danh sách đầy đủ

Bộ đệm giao thức và thiết kế hướng đối tượng Các lớp bộ đệm giao thức về cơ bản là các bộ chứa dữ liệu (như các cấu trúc trong C) không cung cấp chức năng bổ sung; . Nếu bạn muốn thêm hành vi phong phú hơn vào một lớp đã tạo, cách tốt nhất để làm điều này là bọc lớp bộ đệm giao thức đã tạo trong một lớp dành riêng cho ứng dụng. Gói bộ đệm giao thức cũng là một ý tưởng hay nếu bạn không có quyền kiểm soát thiết kế của tệp .proto (ví dụ: nếu bạn đang sử dụng lại một bộ đệm từ một dự án khác). Trong trường hợp đó, bạn có thể sử dụng lớp trình bao bọc để tạo giao diện phù hợp hơn với môi trường duy nhất của ứng dụng của bạn. ẩn một số dữ liệu và phương thức, hiển thị các chức năng tiện lợi, v.v. Bạn không bao giờ nên thêm hành vi vào các lớp được tạo bằng cách kế thừa từ chúng. Điều này sẽ phá vỡ các cơ chế bên trong và dù sao cũng không phải là cách thực hành hướng đối tượng tốt

Viết một tin nhắn

Bây giờ, hãy thử sử dụng các lớp đệm giao thức của bạn. Điều đầu tiên bạn muốn ứng dụng sổ địa chỉ của mình có thể thực hiện là ghi chi tiết cá nhân vào tệp sổ địa chỉ của bạn. Để thực hiện việc này, bạn cần tạo và điền các phiên bản của các lớp bộ đệm giao thức của mình, sau đó ghi chúng vào luồng đầu ra

Đây là một chương trình đọc một

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
3 từ một tệp, thêm một
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
1 mới vào nó dựa trên đầu vào của người dùng và ghi lại
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
3 mới vào tệp một lần nữa. Các phần gọi trực tiếp hoặc mã tham chiếu do trình biên dịch giao thức tạo ra được tô sáng

#! /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()

đọc tin nhắn

Tất nhiên, một cuốn sổ địa chỉ sẽ không được sử dụng nhiều nếu bạn không thể lấy bất kỳ thông tin nào từ nó. Ví dụ này đọc tệp được tạo bởi ví dụ trên và in tất cả thông tin trong đó

#! /usr/bin/python

import addressbook_pb2
import sys

# Iterates though all people in the AddressBook and prints info about them.
def ListPeople(address_book):
  for person in address_book.people:
    print "Person ID:", person.id
    print "  Name:", person.name
    if person.HasField('email'):
      print "  E-mail address:", person.email

    for phone_number in person.phones:
      if phone_number.type == addressbook_pb2.Person.PhoneType.MOBILE:
        print "  Mobile phone #: ",
      elif phone_number.type == addressbook_pb2.Person.PhoneType.HOME:
        print "  Home phone #: ",
      elif phone_number.type == addressbook_pb2.Person.PhoneType.WORK:
        print "  Work phone #: ",
      print phone_number.number

# Main procedure:  Reads the entire address book from a file and prints all
#   the information inside.
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.
f = open(sys.argv[1], "rb")
address_book.ParseFromString(f.read())
f.close()

ListPeople(address_book)

Mở rộng bộ đệm giao thức

Sớm hay muộn sau khi bạn phát hành mã sử dụng bộ đệm giao thức của mình, chắc chắn bạn sẽ muốn "cải thiện" định nghĩa của bộ đệm giao thức. Nếu bạn muốn bộ đệm mới của mình tương thích ngược và bộ đệm cũ của bạn tương thích về phía trước – và bạn gần như chắc chắn muốn điều này – thì có một số quy tắc bạn cần tuân theo. Trong phiên bản mới của bộ đệm giao thức

  • bạn không được thay đổi số thẻ của bất kỳ trường hiện có nào
  • bạn không được thêm hoặc xóa bất kỳ trường bắt buộc nào
  • bạn có thể xóa các trường tùy chọn hoặc lặp lại
  • bạn có thể thêm các trường tùy chọn hoặc trường lặp lại mới nhưng bạn phải sử dụng số thẻ mới (nghĩa là số thẻ chưa bao giờ được sử dụng trong bộ đệm giao thức này, thậm chí không được sử dụng bởi các trường đã xóa)

(Có những quy tắc này, nhưng chúng hiếm khi được sử dụng. )

Nếu bạn tuân theo các quy tắc này, mã cũ sẽ vui vẻ đọc thư mới và chỉ cần bỏ qua mọi trường mới. Đối với mã cũ, các trường tùy chọn đã bị xóa sẽ chỉ có giá trị mặc định và các trường lặp lại đã xóa sẽ trống. Mã mới cũng sẽ đọc rõ ràng các tin nhắn cũ. Tuy nhiên, hãy nhớ rằng các trường tùy chọn mới sẽ không xuất hiện trong thư cũ, vì vậy bạn cần kiểm tra rõ ràng xem chúng có được đặt bằng .proto6 hay không hoặc cung cấp giá trị mặc định hợp lý trong tệp .proto của bạn với ____60_______8 sau số thẻ. Nếu giá trị mặc định không được chỉ định cho phần tử tùy chọn, giá trị mặc định dành riêng cho loại sẽ được sử dụng thay thế. đối với chuỗi, giá trị mặc định là chuỗi rỗng. Đối với booleans, giá trị mặc định là sai. Đối với các loại số, giá trị mặc định là 0. Cũng lưu ý rằng nếu bạn đã thêm một trường mới được lặp lại, mã mới của bạn sẽ không thể biết liệu nó có bị bỏ trống (theo mã mới) hay không bao giờ được đặt (theo mã cũ) vì không có cờ .proto6 cho trường đó

Sử dụng nâng cao

Bộ đệm giao thức có những công dụng vượt xa các trình truy cập và tuần tự hóa đơn giản. Hãy chắc chắn khám phá tài liệu tham khảo API Python để xem bạn có thể làm gì khác với chúng

Một tính năng chính được cung cấp bởi các lớp bản tin giao thức là phản ánh. Bạn có thể lặp lại các trường của một thông báo và thao tác các giá trị của chúng mà không cần viết mã của bạn đối với bất kỳ loại thông báo cụ thể nào. Một cách rất hữu ích để sử dụng sự phản chiếu là chuyển đổi các thông báo giao thức sang và từ các mã hóa khác, chẳng hạn như XML hoặc JSON. Việc sử dụng phản xạ nâng cao hơn có thể là để tìm sự khác biệt giữa hai thông báo cùng loại hoặc để phát triển một loại "biểu thức chính quy cho thông báo giao thức" trong đó bạn có thể viết các biểu thức khớp với nội dung thông báo nhất định. Nếu bạn sử dụng trí tưởng tượng của mình, bạn có thể áp dụng Bộ đệm giao thức cho nhiều vấn đề hơn bạn có thể mong đợi ban đầu