青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

woaidongmao

文章均收錄自他人博客,但不喜標(biāo)題前加-[轉(zhuǎn)貼],因其丑陋,見諒!~
隨筆 - 1469, 文章 - 0, 評論 - 661, 引用 - 0
數(shù)據(jù)加載中……

google ProtoBuf開發(fā)者指南

ProtoBuf開發(fā)者指南

譯者:

gashero

目錄

  • 1   概覽
    • 1.1   什么是protocol buffer
    • 1.2   他們?nèi)绾喂ぷ?
    • 1.3   為什么不用XML?
    • 1.4   聽起來像是為我的解決方案,如何開始?
    • 1.5   一點歷史
  • 2   語言指導(dǎo)
    • 2.1   定義一個消息類型
    • 2.2   值類型
    • 2.3   可選字段與缺省值
    • 2.4   枚舉
    • 2.5   使用其他消息類型
    • 2.6   嵌套類型
    • 2.7   更新一個數(shù)據(jù)類型
    • 2.8   擴展
    • 2.9  
    • 2.10   定義服務(wù)
    • 2.11   選項
    • 2.12   生成你的類
  • 3   代碼風(fēng)格指導(dǎo)
    • 3.1   消息與字段名
    • 3.2   枚舉
    • 3.3   服務(wù)
  • 4   編碼
    • 4.1   一個簡單的消息
    • 4.2   基于128Varints
    • 4.3   消息結(jié)構(gòu)
    • 4.4   更多的值類型
    • 4.5   內(nèi)嵌消息
    • 4.6   可選的和重復(fù)的元素
    • 4.7   字段順序
  • 5   ProtocolBuffer基礎(chǔ):C++
  • 6   ProtocolBuffer基礎(chǔ):Java
  • 7   ProtocolBuffer基礎(chǔ):Python
    • 7.1   為什么使用ProtocolBuffer?
    • 7.2   哪里可以找到例子代碼
    • 7.3   定義你的協(xié)議格式
    • 7.4   編譯你的ProtocolBuffer
    • 7.5   ProtocolBuffer API
      • 7.5.1   枚舉
      • 7.5.2   標(biāo)準(zhǔn)消息方法
      • 7.5.3   解析與串行化
    • 7.6   寫消息
    • 7.7   讀消息
    • 7.8   擴展ProtocolBuffer
    • 7.9   高級使用
  • 8   參考概覽
  • 9   C++代碼生成
  • 10   C++ API
  • 11   Java代碼生成
  • 12   Java API
  • 13   Python代碼生成
    • 13.1   編譯器的使用
    • 13.2  
    • 13.3   消息
    • 13.4   字段
      • 13.4.1   簡單字段
      • 13.4.2   簡單消息字段
      • 13.4.3   重復(fù)字段
      • 13.4.4   重復(fù)消息字段
      • 13.4.5   枚舉類型
      • 13.4.6   擴展
    • 13.5   服務(wù)
      • 13.5.1   接口
      • 13.5.2   存根(Stub)
  • 14   Python API
  • 15   其他語言

 

1   概覽

歡迎來到protocol buffer的開發(fā)者指南文檔,一種語言無關(guān)、平臺無關(guān)、擴展性好的用于通信協(xié)議、數(shù)據(jù)存儲的結(jié)構(gòu)化數(shù)據(jù)串行化方法。

本文檔面向希望使用protocol bufferJavaC++Python開發(fā)者。這個概覽介紹了protocol buffer,并告訴你如何開始,你隨后可以跟隨編程指導(dǎo)( http://code.google.com/apis/protocolbuffers/docs/tutorials.html )深入了解protocol buffer編碼方式( http://code.google.com/apis/protocolbuffers/docs/encoding.html )API參考文檔( http://code.google.com/apis/protocolbuffers/docs/reference/overview.html )同樣也是提供了這三種編程語言的版本,不夠協(xié)議語言( http://code.google.com/apis/protocolbuffers/docs/proto.html )和樣式( http://code.google.com/apis/protocolbuffers/docs/style.html )指導(dǎo)都是編寫 .proto 文件。

 

1.1   什么是protocol buffer

ProtocolBuffer是用于結(jié)構(gòu)化數(shù)據(jù)串行化的靈活、高效、自動的方法,有如XML,不過它更小、更快、也更簡單。你可以定義自己的數(shù)據(jù)結(jié)構(gòu),然后使用代碼生成器生成的代碼來讀寫這個數(shù)據(jù)結(jié)構(gòu)。你甚至可以在無需重新部署程序的情況下更新數(shù)據(jù)結(jié)構(gòu)。

 

1.2   他們?nèi)绾喂ぷ?span lang="EN-US">

你首先需要在一個 .proto 文件中定義你需要做串行化的數(shù)據(jù)結(jié)構(gòu)信息。每個ProtocolBuffer信息是一小段邏輯記錄,包含一系列的鍵值對。這里有個非常簡單的 .proto 文件定義了個人信息:

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

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

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

    repeated PhoneNumber phone=4;
}

有如你所見,消息格式很簡單,每個消息類型擁有一個或多個特定的數(shù)字字段,每個字段擁有一個名字和一個值類型。值類型可以是數(shù)字(整數(shù)或浮點)、布爾型、字符串、原始字節(jié)或者其他ProtocolBuffer類型,還允許數(shù)據(jù)結(jié)構(gòu)的分級。你可以指定可選字段,必選字段和重復(fù)字段。你可以在( http://code.google.com/apis/protocolbuffers/docs/proto.html )找到更多關(guān)于如何編寫 .proto 文件的信息。

一旦你定義了自己的報文格式(message),你就可以運行ProtocolBuffer編譯器,將你的 .proto 文件編譯成特定語言的類。這些類提供了簡單的方法訪問每個字段(像是 query() set_query() ),像是訪問類的方法一樣將結(jié)構(gòu)串行化或反串行化。例如你可以選擇C++語言,運行編譯如上的協(xié)議文件生成類叫做 Person 。隨后你就可以在應(yīng)用中使用這個類來串行化的讀取報文信息。你可以這么寫代碼:

Person person;
person.set_name("John Doe");
person.set_id(1234);
person.set_email("jdoe@example.com");
fstream.output("myfile",ios::out | ios::binary);
person.SerializeToOstream(&output);

然后,你可以讀取報文中的數(shù)據(jù):

fstream input("myfile",ios::in | ios:binary);
Person person;
person.ParseFromIstream(&input);
cout << "Name: " << person.name() << endl;
cout << "E-mail: " << person.email() << endl;

你可以在不影響向后兼容的情況下隨意給數(shù)據(jù)結(jié)構(gòu)增加字段,舊有的數(shù)據(jù)會忽略新的字段。所以如果使用ProtocolBuffer作為通信協(xié)議,你可以無須擔(dān)心破壞現(xiàn)有代碼的情況下擴展協(xié)議。

你可以在API參考( http://code.google.com/apis/protocolbuffers/docs/reference/overview.html )中找到完整的參考,而關(guān)于ProtocolBuffer的報文格式編碼則可以在( http://code.google.com/apis/protocolbuffers/docs/encoding.html )中找到。

 

1.3   為什么不用XML?

ProtocolBuffer擁有多項比XML更高級的串行化結(jié)構(gòu)數(shù)據(jù)的特性,ProtocolBuffer

·   更簡單

·   3-10

·   20-100

·   更少的歧義

·   可以方便的生成數(shù)據(jù)存取類

例如,讓我們看看如何在XML中建模Personnameemail字段:

<person>
    <name>John Doe</name>
    <email>jdoe@example.com</email>
</person>

對應(yīng)的ProtocolBuffer報文則如下:

#ProtocolBuffer的文本表示
#
這不是正常時使用的二進制數(shù)據(jù)
person {
    name: "John Doe"
    email: "jdoe@example.com"
}

當(dāng)這個報文編碼到ProtocolBuffer的二進制格式( http://code.google.com/apis/protocolbuffers/docs/encoding.html )(上面的文本僅用于調(diào)試和編輯),它只需要28字節(jié)和100-200ns的解析時間。而XML的版本需要69字節(jié)(除去空白)5000-10000ns的解析時間。

當(dāng)然,操作ProtocolBuffer也很簡單:

cout << "Name: " << person.name() << endl;
cout << "E-mail: " << person.email() << endl;

XML的你需要:

cout << "Name: "
     << person.getElementsByTagName("name")->item(0)->innerText()
     << endl;
cout << "E-mail: "
     << person.getElementsByTagName("email")->item(0)->innerText()
     << end;

當(dāng)然,ProtocolBuffer并不是在任何時候都比XML更合適,例如ProtocolBuffer無法對一個基于標(biāo)記文本的文檔建模,因為你根本沒法方便的在文本中插入結(jié)構(gòu)。另外,XML是便于人類閱讀和編輯的,而ProtocolBuffer則不是。還有XML是自解釋的,而 ProtocolBuffer僅在你擁有報文格式定義的 .proto 文件時才有意義

 

1.4   聽起來像是為我的解決方案,如何開始?

下載包( http://code.google.com/p/protobuf/downloads/ ),包含了JavaPythonC++ProtocolBuffer編譯器,用于生成你需要的IO類。構(gòu)建和安裝你的編譯器,跟隨README的指令就可以做到。

一旦你安裝好了,就可以跟著編程指導(dǎo)( http://code.google.com/apis/protocolbuffers/docs/tutorials.html )來選擇語言-隨后就是使用ProtocolBuffer創(chuàng)建一個簡單的應(yīng)用了。

 

1.5   一點歷史

ProtocolBuffer最初是在Google開發(fā)的,用以解決索引服務(wù)器的請求、響應(yīng)協(xié)議。在使用ProtocolBuffer之前,有一種格式用以處理請求和響應(yīng)數(shù)據(jù)的編碼和解碼,并且支持多種版本的協(xié)議。而這最終導(dǎo)致了丑陋的代碼,有如:

if (version==3) {
    ...
}else if (version>4) {
    if (version==5) {
        ...
    }
    ...
}

通信協(xié)議因此變得越來越復(fù)雜,因為開發(fā)者必須確保,發(fā)出請求的人和接受請求的人必須同時兼容,并且在一方開始使用新協(xié)議時,另外一方也要可以接受。

ProtocolBuffer設(shè)計用于解決這一類問題:

·   很方便引入新字段,而中間服務(wù)器可以忽略這些字段,直接傳遞過去而無需理解所有的字段。

·   格式可以自描述,并且可以在多種語言中使用(C++Java)

然而用戶仍然需要手寫解析代碼。

隨著系統(tǒng)的演化,他需要一些其他的功能:

·   自動生成編碼和解碼代碼,而無需自己編寫解析器。

·   除了用于簡短的RPC(Remote Procedure Call)請求,人們使用ProtocolBuffer來做數(shù)據(jù)存儲格式(例如BitTable)

·   RPC服務(wù)器接口可以作為 .proto 文件來描述,而通過ProtocolBuffer的編譯器生成存根(stub)類供用戶實現(xiàn)服務(wù)器接口。

ProtocolBuffer現(xiàn)在已經(jīng)是Google的混合語言數(shù)據(jù)標(biāo)準(zhǔn)了,現(xiàn)在已經(jīng)正在使用的有超過48,162種報文格式定義和超過12,183 .proto 文件。他們用于RPC系統(tǒng)和持續(xù)數(shù)據(jù)存儲系統(tǒng)。

 

2   語言指導(dǎo)

本指導(dǎo)描述了如何使用ProtocolBuffer語言來定義結(jié)構(gòu)化數(shù)據(jù)類型,包括 .proto 文件的語法和如何生成存取類。

這是一份指導(dǎo)手冊,一步步的例子使用文檔中的多種功能,查看入門指導(dǎo)( http://code.google.com/apis/protocolbuffers/docs/tutorials.html )選擇你的語言。

 

2.1   定義一個消息類型

@waiting …

 

2.2   值類型

@waiting …

 

2.3   可選字段與缺省值

@waiting …

 

2.4   枚舉

@waiting …

 

2.5   使用其他消息類型

@waiting …

 

2.6   嵌套類型

@waiting …

 

2.7   更新一個數(shù)據(jù)類型

@waiting …

 

2.8   擴展

@waiting …

 

2.9  

@waiting …

 

2.10   定義服務(wù)

@waiting …

 

2.11   選項

@waiting …

 

2.12   生成你的類

@waiting …

 

3   代碼風(fēng)格指導(dǎo)

本文檔提供了 .proto 文件的代碼風(fēng)格指導(dǎo)。按照慣例,你將會,你將會生成一些便于閱讀和一致的ProtocolBuffer定義文件。

 

3.1   消息與字段名

使用駱駝風(fēng)格的大小寫命名,即單詞首字母大寫,來做消息名。使用GNU的全部小寫,使用下劃線分隔的方式定義字段名:

message SongServerRequest {
    required string song_name=1;
}

使用這種命名方式得到的名字如下:

C++:
    const string& song_name() {...}
    void set_song_name(const string& x) {...}

Java:
    public String getSongName() {...}
    public Builder setSongName(String v) {...}

 

3.2   枚舉

使用駱駝風(fēng)格做枚舉名,而用全部大寫做值的名字:

enum Foo {
    FIRST_VALUE=1;
    SECOND_VALUE=2;
}

每個枚舉值最后以分號結(jié)尾,而不是逗號。

 

3.3   服務(wù)

如果你的 .proto 文件定義了RPC服務(wù),你可以使用駱駝風(fēng)格:

service FooService {
    rpc GetSomething(FooRequest) returns (FooResponse);
}

 

4   編碼

本文檔描述了ProtocolBuffer的串行化二進制數(shù)據(jù)格式定義。你如果僅僅是在應(yīng)用中使用ProtocolBuffer,并不需要知道這些,但是這些會對你定義高效的格式有所幫助。

 

4.1   一個簡單的消息

@waiting …

 

4.2   基于128Varints

@waiting …

 

4.3   消息結(jié)構(gòu)

@waiting …

 

4.4   更多的值類型

@waiting …

 

4.5   內(nèi)嵌消息

@waiting …

 

4.6   可選的和重復(fù)的元素

@waiting …

 

4.7   字段順序

@waiting …

 

 

5   ProtocolBuffer基礎(chǔ):C++

@waiting …

 

6   ProtocolBuffer基礎(chǔ):Java

@waiting …

7   ProtocolBuffer基礎(chǔ):Python

本指南給Python程序員一個快速使用的ProtocolBuffer的指導(dǎo)。通過一些簡單的例子來在應(yīng)用中使用ProtocolBuffer,它向你展示了如何:

·   定義 .proto 消息格式文件

·   使用ProtocolBuffer編譯器

·   使用PythonProtocolBuffer編程接口來讀寫消息

這并不是一個在Python中使用ProtocolBuffer的完整指導(dǎo)。更多細節(jié)請參考手冊信息,查看語言指導(dǎo)( http://code.google.com/apis/protocolbuffers/docs/proto.html )Python API( http://code.google.com/apis/protocolbuffers/docs/reference/python/index.html ),和編碼手冊( http://code.google.com/apis/protocolbuffers/docs/encoding.html )

 

7.1   為什么使用ProtocolBuffer?

下面的例子地址本應(yīng)用用于讀寫人的聯(lián)系信息。每個人有nameIDemail,和聯(lián)系人電話號碼。

如何串行化和讀取結(jié)構(gòu)化數(shù)據(jù)呢?有如下幾種問題:

·   使用Pythonpickle,這是語言內(nèi)置的缺省方法,不過沒法演化,也無法讓其他語言支持。

·   你可以發(fā)明一種數(shù)據(jù)編碼方法,例如4個整數(shù)”12:3-23:67″,這是簡單而靈活的方法,不過你需要自己寫解析器代碼,且只適用于簡單的數(shù)據(jù)。

·   串行化數(shù)據(jù)到XML。這種方法因為可讀性和多種語言的兼容函數(shù)庫而顯得比較吸引人,不過這也不是最好的方法,因為XML浪費空間是臭名昭著的,編碼解碼也很浪費時間。而XML DOM樹也是很復(fù)雜的。

ProtocolBuffer提供了靈活、高效、自動化的方法來解決這些問題。通過ProtocolBuffer,只需要寫一個 .proto 數(shù)據(jù)結(jié)構(gòu)描述文件,就可以編譯到幾種語言的自動編碼解碼類。生成的類提供了settergetter方法來控制讀寫細節(jié)。最重要的是 ProtocolBuffer支持后期擴展協(xié)議,而又確保舊格式可以兼容。

 

7.2   哪里可以找到例子代碼

源碼發(fā)行包中已經(jīng)包含了,在”example”文件夾。

 

7.3   定義你的協(xié)議格式

想要創(chuàng)建你的地址本應(yīng)用,需要開始于一個 .proto 文件。定義一個 .proto 文件很簡單:添加一個消息到數(shù)據(jù)結(jié)構(gòu),然后指定一個和一個類型到每一個字段,如下是本次例子使用的 addressbook.proto

package tutorial;

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

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

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

    repeated PhoneNumber phone=4;
}

message AddressBook {
    repeated Person person=1;
}

有如你所見的,語法類似于C++Java。讓我們分塊理解他們。

@waiting …

 

7.4   編譯你的ProtocolBuffer

現(xiàn)在已經(jīng)擁有了 .proto 文件,下一步就是編譯生成相關(guān)的訪問類。運行編譯器 protoc 編譯你的 .proto 文件。

1.    如果還沒安裝編譯器則下載并按照README的安裝。

2.    運行編譯器,指定源目錄和目標(biāo)目錄,定位你的 .proto 文件到源目錄,然后執(zhí)行:

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

因為需要使用Python類,所以 –python_out 選項指定了特定的輸出語言。

這個步驟會生成 addressbook_pb2.py 到目標(biāo)目錄。

 

7.5   ProtocolBuffer API

不像生成的C++Java代碼,Python生成的類并不會直接為你生成存取數(shù)據(jù)的代碼。而是(有如你在 addressbook_pb2.py 中見到的)生成消息描述、枚舉、和字段,還有一些神秘的空類,每個對應(yīng)一個消息類型:

class Person(message.Message):
    __metaclass__=reflection.GeneratedProtocolMessageType

    class PhoneNumber(message.Message):
        __metaclass__=reflection.GeneratedProtocolMessageType
        DESCRIPTION=_PERSON_PHONENUMBER

    DESCRIPTOR=_PERSON

class AddressBook(message.Message):
    __metaclass__=reflection.GeneratedProtocolMessageType
    DESCRIPTOR=_ADDRESSBOOK

這里每個類最重要的一行是 __metaclass__=reflection.GeneratedProtocolMessageType 。通過Python的元類機制工作,你可以把他們看做是生成類的模板。在載入時, GeneratedProtocolMessageType 元類使用特定的描述符創(chuàng)建Python方法。隨后你就可以使用完整的功能了。

最后就是你可以使用 Person 類來操作相關(guān)字段了。例如你可以寫:

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

需要注意的是這些賦值屬性并不是簡單的增加新字段到Python對象,如果你嘗試給一個 .proto 文件中沒有定義的字段賦值,就會拋出 AttributeError 異常,如果賦值類型錯誤會拋出 TypeError 。在給一個字段賦值之前讀取會返回缺省值:

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

更多相關(guān)信息參考( http://code.google.com/apis/protocolbuffers/docs/reference/python-generated.html )

7.5.1   枚舉

枚舉在元類中定義為一些符號常量對應(yīng)的數(shù)字。例如常量 addressbook_pb2.Person.WORK 擁有值2

7.5.2   標(biāo)準(zhǔn)消息方法

每個消息類包含一些其他方法允許你檢查和控制整個消息,包括:

·   IsInitialized() :檢查是否所有必須(required)字段都已經(jīng)被賦值了。

·   __str__() :返回人類可讀的消息表示,便于調(diào)試。

·   CopyFrom(other_msg) :使用另外一個消息的值來覆蓋本消息。

·   Clear() :清除所有元素的值,回到初識狀態(tài)。

這些方法是通過接口 Message 實現(xiàn)的,更多消息參考( http://code.google.com/apis/protocolbuffers/docs/reference/python/google.protobuf.message.Message-class.html )

7.5.3   解析與串行化

最后,每個ProtocolBuffer類有些方法用于讀寫消息的二進制數(shù)據(jù)( http://code.google.com/apis/protocolbuffers/docs/encoding.html )。包括:

·   SerializeToString() :串行化,并返回字符串。注意是二進制格式而非文本。

·   ParseFromString(data) :解析數(shù)據(jù)。

他們是成對使用的,提供二進制數(shù)據(jù)的串行化和解析。另外參考消息API參考( http://code.google.com/apis/protocolbuffers/docs/reference/python/google.protobuf.message.Message-class.html )了解更多信息。

Note

ProtocolBuffer與面向?qū)ο笤O(shè)計

ProtocolBuffer類只是用于存取數(shù)據(jù)的,類似于C++中的結(jié)構(gòu)體,他們并沒有在面向?qū)ο蠓矫孀龊芎玫脑O(shè)計。如果你想要給這些類添加更多的行為,最好的方法是包裝(wrap)。包裝同樣適合于復(fù)用別人寫好的 .proto 文件。這種情況下,你可以把ProtocolBuffer生成類包裝的很適合于你的應(yīng)用,并隱藏一些數(shù)據(jù)和方法,暴露有用的函數(shù)等等。 你不可以通過繼承來給自動生成的類添加行為。 這會破壞他們的內(nèi)部工作機制。

7.6   寫消息

現(xiàn)在開始嘗試使用ProtocolBuffer的類。第一件事是讓地址本應(yīng)用可以記錄聯(lián)系人的細節(jié)信息。想要做這些需要先創(chuàng)建聯(lián)系人實例,然后寫入到輸出流。

這里的程序從文件讀取地址本,添加新的聯(lián)系人信息,然后寫回新的地址本到文件。

#! /usr/bin/python
import addressbook_pb2
import sys

#
這個函數(shù)使用用戶輸入填充聯(lián)系人信息
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.phone.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.MOBILE
        elif type=="home":
            phone_number.type=addressbook_pb2.Person.HOME
        elif type=="work":
            phone_number.type=addressbook_pb2.Person.WORK
        else:
            print "Unknown phone type; leaving as default value."

#
主函數(shù),從文件讀取地址本,添加新的聯(lián)系人,然后寫回到文件
if len(sys.argv)!=2:
    print "Usage:",sys.argv[0],"ADDRESS_BOOK_FILE"
    sys.exit(-1)

address_book=addressbook_pb2.AddressBook()

#
讀取已經(jīng)存在的地址本
try:
    f=open(sys.argv[1],"fb")
    address_book.ParseFromString(f.read())
    f.close()
except OSError:
    print sys.argv[1]+": Count open file. Creating a new one."

#
添加地址
PromptFromAddress(address_book.person.add())

#
寫入到文件
f=open(sys.argv[1],"wb")
f.write(address_book.SerializeToString())
f.close()

7.7   讀消息

當(dāng)然,一個無法讀取的地址本是沒什么用處的,這個例子讀取剛才創(chuàng)建的文件并打印所有信息:

#! /usr/bin/python

import addressbook_pb2
import sys

#
遍歷地址本中所有的人并打印出來
def ListPeople(address_book):
    for person in address_book.person:
        print "Person ID:",person.id
        print "  Name:",person.name
        if person.HasField("email"):
            print "  E-mail:",person.email
        for phone_number in person.phone:
            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

#
主函數(shù),從文件讀取地址本
if len(sys.argv)!=2:
    print "Usage:",sys.argv[0],"ADDRESS_BOOK_FILE"
    sys.exit(-1)

address_book=addressbook_pb2.AddressBook()

#
讀取整個地址本文件
f=open(sys.argv[1],"rb")
address_book.ParseFromString(f.read())
f.close()

ListPeople(address_book)

7.8   擴展ProtocolBuffer

在你發(fā)不了代碼以后,可能會想要改進ProtocolBuffer的定義。如果你想新的數(shù)據(jù)結(jié)構(gòu)向后兼容,而你的舊數(shù)據(jù)可以向前兼容,那么你就找對了東西了,不過有些規(guī)則需要遵守。在新版本的ProtocolBuffer中:

·   必須不可以改變已經(jīng)存在的標(biāo)簽的數(shù)字。

·   必須不可以增加或刪除必須(required)字段。

·   可以刪除可選(optional)或重復(fù)(repeated)字段。

·   可以添加新的可選或重復(fù)字段,但是必須使用新的標(biāo)簽數(shù)字,必須是之前的字段所沒有用過的。

這些規(guī)則也有例外( http://code.google.com/apis/protocolbuffers/docs/proto.html#updating ),不過很少使用。

如果你遵從這些規(guī)則,舊代碼會很容易的讀取新的消息,并簡單的忽略新的字段。而對舊的被刪除的可選字段也會簡單的使用他們的缺省值,被刪除的重復(fù)字段會自動為空。新的代碼也會透明的讀取舊的消息。然而,需要注意的是新的可選消息不會在舊的消息中顯示,所以你需要使用 has_ 嚴格的檢查他們是否存在,或者在 .proto 文件中提供一個缺省值。如果沒有缺省值,就會有一個類型相關(guān)的默認缺省值:對于字符串就是空字符串;對于布爾型則是false;對于數(shù)字類型默認為0。同時要注意的是如果你添加了新的重復(fù)字段,你的新代碼不會告訴你這個字段為空(新代碼)也不會,也不會(舊代碼)包含 has_ 標(biāo)志。

 

7.9   高級使用

ProtocolBuffer不僅僅提供了數(shù)據(jù)結(jié)構(gòu)的存取和串行化。查看Python API參考( http://code.google.com/apis/protocolbuffers/docs/reference/python/index.html )了解更多功能。

一個核心功能是通過消息類的映射(reflection)提供的。你可以通過它遍歷消息的所有字段,和管理他們的值。關(guān)于映射的一個很有用的地方是轉(zhuǎn)換到其他編碼,如XMLJSON。一個使用映射的更高級的功能是尋找同類型兩個消息的差異,或者開發(fā)出排序、正則表達式等功能。使用你的創(chuàng)造力,還可以用ProtocolBuffer實現(xiàn)比你以前想象的更多的問題。

映射是通過消息接口提供的。

 

8   參考概覽

@waiting …

9   C++代碼生成

@waiting …

10   C++ API

@waiting …

11   Java代碼生成

@waiting …

12   Java API

@waiting …

13   Python代碼生成

本頁提供了Python生成類的相關(guān)細節(jié)。你可以在閱讀本文檔之前查看語言指導(dǎo)。

PythonProtocolBuffer實現(xiàn)與C++Java的略有不同,編譯器只輸出構(gòu)建代碼的描述符來生成類,而由Python的元類來執(zhí)行工作。本文檔描述了元類開始生效以后的東西。

 

13.1   編譯器的使用

ProtocolBuffer通過編譯器的 –python_out= 選項來生成Python的相關(guān)類。這個參數(shù)實際上是指定輸出的Python類放在哪個目錄下。編譯器會為每個 .proto 文件生成一個對應(yīng)的 .py 文件。輸出文件名與輸入文件名相關(guān),不過有兩處修改:

·   擴展名 .proto 改為 .py

·   路徑名的修改。

如果你按照如下調(diào)用編譯器:

protoc --proto_path=src --python_out=build/gen src/foo.proto src/bar/baz.proto

編譯器會自動讀取兩個 .proto 文件然后產(chǎn)生兩個輸出文件。在需要時編譯器會自動創(chuàng)建目錄,不過 –python_out 指定的目錄不會自動創(chuàng)建。

需要注意的是,如果 .proto 文件名或路徑包含有無法在Python中使用的模塊名(如連字符),就會被自動轉(zhuǎn)換為下劃線。所以文件 foo-bar.proto 會變成 foo_bar_pb2.py

Note

在每個文件后綴的 _pb2.py 中的2代表ProtocolBuffer版本2。版本1僅在Google內(nèi)部使用,但是你仍然可以在以前發(fā)布的一些代碼中找到它。自動版本2開始,ProtocolBuffer開始使用完全不同的接口了,從此Python也沒有編譯時類型檢查了,我們加上這個版本號來標(biāo)志Python文件名。

13.2  

Python代碼生成根本不在乎包的名字。因為Python使用目錄名來做包名。

13.3   消息

先看看一個簡單的消息聲明:

message Foo {}

ProtocolBuffer編譯器會生成類Foo,它是 google.protobuf.Message 的子類。這個實體類,不含有虛擬方法。不像C++JavaPython生成類對優(yōu)化選項不感冒;實際上Python的生成代碼已經(jīng)為代碼大小做了優(yōu)化。

你不能繼承Foo的子類。生成類被設(shè)計不可以被繼承,否則會被打破一些設(shè)計。另外,繼承本類也是不好的設(shè)計。

Python的消息類沒有特定的公共成員,而是定義接口,極其嵌套的字段、消息和枚舉類型。

一個消息可以在另外一個消息中聲明,例如 message Foo { message Bar {}} 。在這種情況下,Bar類定義為Foo的一個靜態(tài)成員,所以你可以通過 Foo.Bar 來引用。

13.4   字段

對于消息類型中的每一個字段,都有對應(yīng)的同名成員。

13.4.1   簡單字段

如果你有一個簡單字段(包括可選的和重復(fù)的),也就是非消息字段,你可以通過簡單字段的方式來管理,例如foo字段的類型是int32,你可以:

message.foo=123
print message.foo

注意設(shè)置foo的值,如果類型錯誤會拋出TypeError

如果foo在賦值之前就讀取,就會使用缺省值。想要檢查是否已經(jīng)賦值,可以用 HasField() ,而清除該字段的值用 ClearField() 。例如:

assert not message.HasField("foo")
message.foo=123
assert message.HasField("foo")
message.ClearField("foo")
assert not message.HasField("foo")

13.4.2   簡單消息字段

消息類型工作方式略有不同。你無法為一個嵌入消息字段賦值。而是直接操作這個消息的成員。因為實例化上層消息時,其包含的子消息同時也實例化了,例如定義:

message Foo {
    optional Bar bar=1;
}

message bar {
    optional int32 i=1;
}

你不可以這么做,因為不能做消息類型字段的賦值:

foo=Foo()
foo.bar=Bar()   #WRONG!

而是可以直接對消息類型字段的成員賦值:

foo=Foo()
assert not foo.HasField("bar")
foo.bar.i=1
assert foo.HasField("bar")

注意簡單的讀取消息類型字段的未賦值成員只不過是打印其缺省值:

foo=Foo()
assert not foo.HasField("bar")
print foo.bar.i #
打印i的缺省值
assert not foo.HasField("bar")

13.4.3   重復(fù)字段

重復(fù)字段表現(xiàn)的像是Python的序列類型。如果是嵌入的消息,你無法為字段直接賦值,但是你可以管理。例如給定的定義:

message Foo {
    repeated int32 nums=1;
}

你就可以這么做:

foo=Foo()
foo.nums.append(15)
foo.nums.append(32)
assert len(foo.nums)==2
assert foo.nums[0]==15
assert foo.nums[1]==32
for i in foo.nums:
    print i
foo.nums[1]=56
assert foo.nums[1]==56

作為一種簡單字段,清除該字段必須使用 ClearField()

13.4.4   重復(fù)消息字段

重復(fù)消息字段工作方式與重復(fù)字段很像,除了 add() 方法用于返回新的對象以外。例如如下定義:

message Foo {
    repeated Bar bar=1;
}

message Bar {
    optional int32 i=1;
}

你可以這么做:

foo=Foo()
bar=foo.bars.add()
bar.i=15
bar=foo.bars.add()
bar.i=32
assert len(foo.bars)==2
assert foo.bars[0].i==15
assert foo.bars[1].i==32
for bar in foo.bars:
    print bar.i
foo.bars[1].i=56
assert foo.bars[1].i==56

13.4.5   枚舉類型

@waiting …

13.4.6   擴展

@waiting …

 

13.5   服務(wù)

 

13.5.1   接口

一個簡單的接口定義:

service Foo {
    rpc Bar(FooRequest) returns(FooResponse);
}

ProtocolBuffer的編譯器會生成類 Foo 來展示這個服務(wù)。 Foo 將會擁有每個服務(wù)定義的方法。在這種情況下 Bar 方法的定義是:

def Bar(self,rpc_controller,request,done)

參數(shù)等效于 Service.CallMethod() ,除了隱含的 method_descriptor 參數(shù)。

這些生成的方法被定義為可以被子類重載。缺省實現(xiàn)只是簡單的調(diào)用 controller.SetFailed() 而拋出錯誤信息告之尚未實現(xiàn)。然后調(diào)用done回調(diào)。在實現(xiàn)你自己的服務(wù)時,你必須繼承生成類,然后重載各個接口方法。

Foo繼承了 Service 接口。ProtocolBuffer編譯器會自動聲響相關(guān)的實現(xiàn)方法:

·   GetDescriptor :返回服務(wù)的 ServiceDescriptor

·   CallMethod :檢測需要調(diào)用哪個方法,并且直接調(diào)用。

·   GetRequestClass GetResponseClass :返回指定方法的請求和響應(yīng)類。

13.5.2   存根(Stub)

ProtocolBuffer編譯器也會為每個服務(wù)接口提供一個存根實現(xiàn),用于客戶端發(fā)送請求到服務(wù)器。對于Foo服務(wù),存根實現(xiàn)是 Foo_Stub

Foo_Stub Foo的子類,他的構(gòu)造器是一個 RpcChannel 。存根會實現(xiàn)調(diào)用每個服務(wù)方法的 CallMethod()

ProtocolBuffer哭并不包含RPC實現(xiàn)。然而,它包含了你構(gòu)造服務(wù)類的所有工具,不過選擇RPC實現(xiàn)則隨你喜歡。你只需要提供 RpcChannel RpcController 的實現(xiàn)即可。

 

14   Python API

@waiting …

15   其他語言

http://m.shnenglu.com/liquidx

 

posted on 2009-06-23 21:04 肥仔 閱讀(72303) 評論(6)  編輯 收藏 引用 所屬分類: 網(wǎng)絡(luò)編程

評論

# re: google ProtoBuf開發(fā)者指南  回復(fù)  更多評論   

謝謝博主的努力,希望能快點看到python的API部分
2010-12-03 14:27 | image72

# re: google ProtoBuf開發(fā)者指南[未登錄]  回復(fù)  更多評論   

非常好!希望完善c++ 及其他部分!
2013-02-27 14:02 | kevin

# re: google ProtoBuf開發(fā)者指南  回復(fù)  更多評論   

請問一下,如果c++的相對較復(fù)雜的一些message,在解析和打包網(wǎng)絡(luò)傳輸時,用protobuf后,還是ParseFromString,SerializeToString到一個string中?還是怎么處理?
2013-05-02 10:20 | ask

# re: google ProtoBuf開發(fā)者指南[未登錄]  回復(fù)  更多評論   

別提問了。。這只是個翻譯而已。。。我以前也總有翻譯英文文章的沖動,現(xiàn)在,完全沒了~
還是學(xué)好英文要緊~
2013-07-08 17:24 | Andy

# re: google ProtoBuf開發(fā)者指南  回復(fù)  更多評論   

真心不知道這位大牛寫什么的,這個東東要這么介紹么。。。。。。。你是教師呢嗎??
2014-04-22 09:46 | chull
青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            亚洲国产日韩欧美一区二区三区| 亚洲伊人网站| 一区二区精品| 亚洲精品免费一二三区| 亚洲精品黄网在线观看| 亚洲高清久久| 亚洲毛片播放| 亚洲欧美日韩精品久久久久| 亚洲女同性videos| 午夜在线视频一区二区区别| 欧美一区二区免费| 另类激情亚洲| 亚洲国产精品久久久| 久久最新视频| 亚洲精品久久久久久下一站| 一本色道久久综合狠狠躁篇的优点| 99精品久久久| 欧美一区二区三区婷婷月色| 欧美一站二站| 欧美日本亚洲视频| 国产欧亚日韩视频| 亚洲激情视频网站| 午夜精品久久久久| 看片网站欧美日韩| 91久久一区二区| 欧美激情一区三区| 欧美成人国产一区二区| 国产精品高清一区二区三区| 亚洲精品欧美精品| 一本久道久久综合中文字幕| 亚洲一区二区精品在线| 久久免费午夜影院| 一本久道久久综合狠狠爱| 香蕉尹人综合在线观看| 欧美精品一区二区三区久久久竹菊| 国产精品高清免费在线观看| 亚洲第一区色| 午夜精品久久久久久久99水蜜桃| 久久综合一区二区| 亚洲一区二区三区乱码aⅴ蜜桃女 亚洲一区二区三区乱码aⅴ | 欧美一区二区观看视频| 欧美成人综合网站| 亚洲欧美国产77777| 欧美久久综合| 91久久国产自产拍夜夜嗨| 午夜精品视频网站| 99视频精品免费观看| 免费美女久久99| 精品成人在线| 欧美一区视频在线| 亚洲一区日本| 国产精品久久久久久久9999| 一区二区电影免费在线观看| 亚洲电影在线| 久久人人爽人人爽| 黑人一区二区| 久久久久久久91| 亚洲欧美在线看| 国产欧美日本一区视频| 亚洲专区一区| 亚洲一区美女视频在线观看免费| 欧美日韩网址| 亚洲一区观看| 亚洲一区二区伦理| 国产精品毛片在线看| 亚洲欧美日韩另类| 亚洲免费视频网站| 国产亚洲精品aa午夜观看| 久久精品亚洲热| 久久久久久久激情视频| 国产在线不卡| 欧美成人精品一区二区三区| 麻豆成人综合网| 亚洲国产一区在线| 91久久线看在观草草青青| 欧美成在线视频| 欧美成人综合| 欧美成人精品激情在线观看| 久久久久久亚洲精品不卡4k岛国| 韩国女主播一区二区三区| 久久综合狠狠综合久久综合88| 久久久久国产精品人| 亚洲第一中文字幕| 亚洲国产日韩在线一区模特| 欧美精品久久99久久在免费线| 9国产精品视频| 一本色道综合亚洲| 国产一区二区三区在线观看免费视频| 欧美与黑人午夜性猛交久久久| 久久激情久久| 一区二区高清在线| 欧美一区=区| 亚洲美女尤物影院| 亚洲男人第一网站| 亚洲欧洲日产国码二区| 中日韩视频在线观看| 依依成人综合视频| 一本色道婷婷久久欧美| 影音欧美亚洲| 亚洲视频精品在线| 亚洲第一精品在线| 亚洲综合电影| 亚洲人在线视频| 亚洲欧洲99久久| 一区二区三区视频在线观看| 久久黄色网页| 西西裸体人体做爰大胆久久久 | 久久丁香综合五月国产三级网站| 亚洲国产精品久久久久秋霞蜜臀| 日韩一区二区精品视频| 揄拍成人国产精品视频| 一本色道久久88精品综合| 尤物在线观看一区| 亚洲欧美激情视频| 一二三四社区欧美黄| 久久精品日产第一区二区三区 | 国产亚洲欧美aaaa| 夜夜精品视频| 亚洲日本中文| 久久久久久自在自线| 亚洲免费在线观看| 欧美成人精品h版在线观看| 久久久久国产精品麻豆ai换脸| 欧美激情综合色| 欧美成人激情视频| 禁断一区二区三区在线| 亚洲欧美清纯在线制服| 99视频超级精品| 亚洲线精品一区二区三区八戒| 麻豆精品网站| 免费成人激情视频| 国产亚洲亚洲| 欧美在线资源| 久久精品国产99| 国产精品一国产精品k频道56| 亚洲美洲欧洲综合国产一区| 91久久精品一区二区别| 国产亚洲一级高清| 一区二区三区在线观看视频| 欧美电影在线观看完整版| 国产一区二区三区黄视频| 亚洲视频久久| 香蕉久久夜色精品国产| 欧美日韩在线免费| 99国产麻豆精品| 99国产精品久久久久久久久久| 欧美大学生性色视频| 亚洲电影av| 亚洲国产精品久久91精品| 米奇777在线欧美播放| 亚洲国产精品久久久久秋霞不卡| 亚洲国产成人在线播放| 欧美第十八页| 亚洲免费观看在线观看| 午夜激情亚洲| 国产日韩精品在线播放| 久久激情五月激情| 亚洲第一区中文99精品| 99re8这里有精品热视频免费| 欧美日韩国产精品| 亚洲一区在线观看视频| 久久久国产91| 亚洲精品国产精品乱码不99按摩| 欧美精品一区二区三区在线看午夜 | 国语自产精品视频在线看抢先版结局 | 欧美ab在线视频| 91久久精品一区| 亚洲女同同性videoxma| 国内精品久久久| 裸体素人女欧美日韩| 99热精品在线观看| 久久综合色8888| 亚洲视频视频在线| 国产日产欧美一区| 欧美高清在线视频观看不卡| 中日韩高清电影网| 欧美77777| 午夜在线观看欧美| 99精品视频网| 国产主播喷水一区二区| 欧美激情精品久久久| 亚洲永久视频| 亚洲欧洲一区二区在线播放| 久久超碰97人人做人人爱| 亚洲另类在线一区| 国产一区二区精品久久99| 欧美福利一区二区| 欧美一区二区三区精品| 亚洲精品一区二| 久久青青草综合| 亚洲综合视频一区| 亚洲精品视频在线播放| 国产亚洲午夜高清国产拍精品| 欧美日韩一区三区| 欧美黄色小视频| 久久亚洲免费| 久久精品国产欧美亚洲人人爽| 亚洲精品少妇网址| 亚洲国产精品久久精品怡红院| 亚洲综合色在线|