知識(shí)共享—protobuf介紹使用及api雷驚風(fēng)_第1頁(yè)
知識(shí)共享—protobuf介紹使用及api雷驚風(fēng)_第2頁(yè)
知識(shí)共享—protobuf介紹使用及api雷驚風(fēng)_第3頁(yè)
知識(shí)共享—protobuf介紹使用及api雷驚風(fēng)_第4頁(yè)
知識(shí)共享—protobuf介紹使用及api雷驚風(fēng)_第5頁(yè)
已閱讀5頁(yè),還剩19頁(yè)未讀 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說(shuō)明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡(jiǎn)介

1、ProtoBuf開(kāi)發(fā)者指南 i概覽o1.1什么是protocolbuffero1.2他們?nèi)绾喂ぷ鱫1.3為什么不用XML?o1.4聽(tīng)起來(lái)像是為我的解決方案,如何開(kāi)始o(jì)1.5一點(diǎn)歷史 2語(yǔ)言指導(dǎo)o2.1定義一個(gè)消息類型o2.2值類型o2.3可選字段與缺省值o2.4枚舉o2.5使用其他消息類型o2.6嵌套類型o2.7更新一個(gè)數(shù)據(jù)類型o2.8擴(kuò)展o2.9包o2.10定義服務(wù)o2.11選項(xiàng)o2.12生成你的類 3代碼風(fēng)格指導(dǎo)o3.1消息與字段名o3.2枚舉o3.3服務(wù) 4編碼o4.1一個(gè)簡(jiǎn)單的消息o4.2基于128的Varintso4.3消息結(jié)構(gòu)o4.4更多的值類型o4.5內(nèi)嵌消息o4.6可選的和重復(fù)

2、的元素o4.7字段順序 5ProtocolBuffer基礎(chǔ):C+ 6ProtocolBuffer基礎(chǔ):Java 7ProtocolBuffer基礎(chǔ):Pythono7.1為什么使用ProtocolBuffer?o7.2哪里可以找到例子代碼o7.3定義你的協(xié)議格式o7.4編譯你的ProtocolBuffero7.5ProtocolBufferAPI7.5.1 枚舉7.5.2 標(biāo)準(zhǔn)消息方法7.5.3 解析與串行化07.6寫消息07.7讀消息07.8擴(kuò)展ProtocolBuffer07.9高級(jí)使用1.1.1 8參考概覽2.2.2 9C+代碼生成3.3.3 10C+API4.4.4 11Java代碼生成

3、112JavaAPI5.5.5 13Python代碼生成o13.1編譯器的使用o13.2包o13.3消息o13.4字段 簡(jiǎn)單字段 簡(jiǎn)單消息字段 重復(fù)字段 重復(fù)消息字段 枚舉類型 擴(kuò)展o13.5服務(wù) 接口 存根(Stub)14PythonAPI15其他語(yǔ)言1概覽歡迎來(lái)到protocolbuffer的開(kāi)發(fā)者指南文檔,一種語(yǔ)言無(wú)關(guān)、平臺(tái)無(wú)關(guān)、擴(kuò)展性好的用于通信協(xié)議、數(shù)據(jù)存儲(chǔ)的結(jié)構(gòu)化數(shù)據(jù)串行化方法。本文檔面向希望使用protocolbuffer的Java、C+或Python開(kāi)發(fā)者。這個(gè)概覽介紹了protocolbuffer,并告訴你如何開(kāi)始,你隨后可以跟隨編程指導(dǎo)(語(yǔ)言的版本,不夠協(xié)議語(yǔ)言( 什么是p

4、rotocolbufferProtocolBuffer是用于結(jié)構(gòu)化數(shù)據(jù)串行化的靈活、高效、自動(dòng)的方法,有如XML,不過(guò)它更小、更快、也更簡(jiǎn)單。你可以定義自己的數(shù)據(jù)結(jié)構(gòu),然后使用代碼生成器生成的代碼來(lái)讀寫這個(gè)數(shù)據(jù)結(jié)構(gòu)。你甚至可以在無(wú)需重新部署程序的情況下更新數(shù)據(jù)結(jié)構(gòu)。 他們?nèi)绾喂ぷ髂闶紫刃枰谝粋€(gè).proto文件中定義你需要做串行化的數(shù)據(jù)結(jié)構(gòu)信息。每個(gè)ProtocolBuffer信息是一小段邏輯記錄,包含一系列的鍵值對(duì)。這里有個(gè)非常簡(jiǎn)單的.proto文件定義了個(gè)人信息:messagePersonrequiredstringname=1;requiredint32id=2;optionalstri

5、ngemail=3;enumPhoneTypeMOBILE=0;HOME=1;WORK=2;messagePhoneNumberrequiredstringnumber=1;optionalPhoneTypetype=2default=HOME;repeatedPhoneNumberphone=4;有如你所見(jiàn),消息格式很簡(jiǎn)單,每個(gè)消息類型擁有一個(gè)或多個(gè)特定的數(shù)字字段,每個(gè)字段擁有一個(gè)名字和一個(gè)值類型。值類型可以是數(shù)字(整數(shù)或浮點(diǎn)卜布爾型、字符串、原始字節(jié)或者其他ProtocolBuffer類型,還允許數(shù)據(jù)結(jié)構(gòu)的分級(jí)。你可以指定可選字段,必選字段和重復(fù)字段。你可以在(一旦你定義了自己的報(bào)文格式(

6、message),你就可以運(yùn)行ProtocolBuffer編譯器,將你的.proto文件編譯成特定語(yǔ)言的類。這些類提供了簡(jiǎn)單的方法訪問(wèn)每個(gè)字段(像是query()和set_query(),像是訪問(wèn)類的方法一樣將結(jié)構(gòu)串行化或反串行化。例如你可以選擇C+語(yǔ)言,運(yùn)行編譯如上的協(xié)議文件生成類叫做Person。隨后你就可以在應(yīng)用中使用這個(gè)類來(lái)串行化的讀取報(bào)文信息。你可以這么寫代碼:Personperson;person.set_name("JohnDoe");person.set_id(1234);person.set_email("jdoe");fstream.

7、output("myfile",ios二out|ios二binary);person.SerializeToOstream(&output);然后,你可以讀取報(bào)文中的數(shù)據(jù):fstreaminput("myfile",ios:in|ios:binary);Personperson;person.ParseFromIstream(&input);cout<<"Name:"<<()<<endl;cout<<"E-mail:"<&l

8、t;person.email()<<endl;你可以在不影響向后兼容的情況下隨意給數(shù)據(jù)結(jié)構(gòu)增加字段,舊有的數(shù)據(jù)會(huì)忽略新的字段。所以如果使用ProtocolBuffer作為通信協(xié)議,你可以無(wú)須擔(dān)心破壞現(xiàn)有代碼的情況下擴(kuò)展協(xié)議。你可以在API參考(整的參考,而關(guān)于ProtocolBuffer的報(bào)文格式編碼則可以在( 為什么不用XML?ProtocolBuffer擁有多項(xiàng)比XML更高級(jí)的串行化結(jié)構(gòu)數(shù)據(jù)的特性,ProtocolBuffer1.1.1 更簡(jiǎn)單2.2.2 小3-10倍3.3.3 快20-100倍4.4.4 更少的歧義5.5.5 可以方便的生成數(shù)據(jù)存取類例如,讓我們看看如何在XM

9、L中建模Person的name和email字段:<person><name>JohnDoe</name><email>jdoe</email></person>對(duì)應(yīng)的ProtocolBuffer報(bào)文則如下:#ProtocolBuffer的文本表示#這不是正常時(shí)使用的二進(jìn)制數(shù)據(jù)personname:"JohnDoe"email:"jdoe)當(dāng)這個(gè)報(bào)文編碼到ProtocolBuffer的二進(jìn)制格式(只需要28字節(jié)和100-200ns的解析時(shí)間。而XML的版本需要69字節(jié)(除去空白)和5000-10

10、000ns的解析時(shí)間。當(dāng)然,操作ProtocolBuffer也很簡(jiǎn)單:cout<<"Name:"<<()<<endl;cout<<"E-mail:"<<person.email()<<endl;而XML的你需要:cout<<"Name:"<<person.getElementsByTagName("name")->item(0)->innerText()<<endl;cout

11、<<"E-mail:"<<person.getElementsByTagName("email")->item(0)->innerText()<<end;當(dāng)然,ProtocolBuffer并不是在任何時(shí)候都比XML更合適,例如ProtocolBuffer無(wú)法對(duì)一個(gè)基于標(biāo)記文本的文檔建模,因?yàn)槟愀緵](méi)法方便的在文本中插入結(jié)構(gòu)。另外,XML是便于人類閱讀和編輯的,而ProtocolBuffer則不是。還有XML是自解釋的,而ProtocolBuffer僅在你擁有報(bào)文格式定義的.proto文件時(shí)才有意義。聽(tīng)起來(lái)像

12、是為我的解決方案,如何開(kāi)始?下載包(http:編譯器,用于生成你需要的IO類。構(gòu)建和安裝你的編譯器,跟隨README的指令就可以做到。一旦你安裝好了,就可以跟著編程指導(dǎo)(來(lái)選擇語(yǔ)言-隨后就是使用ProtocolBuffer創(chuàng)建一個(gè)簡(jiǎn)單的應(yīng)用了。一點(diǎn)歷史ProtocolBuffer最初是在Google開(kāi)發(fā)的,用以解決索引服務(wù)器的請(qǐng)求、響應(yīng)協(xié)議。在使用ProtocolBuffer之前,有一種格式用以處理請(qǐng)求和響應(yīng)數(shù)據(jù)的編碼和解碼,并且支持多種版本的協(xié)議。而這最終導(dǎo)致了丑陋的代碼,有如:if(version=3)elseif(version>4)if(version=5)通信協(xié)議因此變得越來(lái)越

13、復(fù)雜,因?yàn)殚_(kāi)發(fā)者必須確保,發(fā)出請(qǐng)求的人和接受請(qǐng)求的人必須同時(shí)兼容,并且在一方開(kāi)始使用新協(xié)議時(shí),另外一方也要可以接受。ProtocolBuffer設(shè)計(jì)用于解決這一類問(wèn)題:很方便引入新字段,而中間服務(wù)器可以忽略這些字段,直接傳遞過(guò)去而無(wú)需理解所有的字段。格式可以自描述,并且可以在多種語(yǔ)言中使用(C+、Java等)然而用戶仍然需要手寫解析代碼。隨著系統(tǒng)的演化,他需要一些其他的功能:自動(dòng)生成編碼和解碼代碼,而無(wú)需自己編寫解析器。除了用于簡(jiǎn)短的RPC(RemoteProcedureCall)請(qǐng)求,人們使用ProtocolBuffer來(lái)做數(shù)據(jù)存儲(chǔ)格式(例如BitTable)。RPC服務(wù)器接口可以作為.pr

14、oto文件來(lái)描述,而通過(guò)ProtocolBuffer的編譯器生成存根(stub)類供用戶實(shí)現(xiàn)服務(wù)器接口。ProtocolBuffer現(xiàn)在已經(jīng)是Google的混合語(yǔ)言數(shù)據(jù)標(biāo)準(zhǔn)了,現(xiàn)在已經(jīng)正在使用的有超過(guò)48,162種報(bào)文格式定義和超過(guò)12,183個(gè).proto文件。他們用于RPC系統(tǒng)和持續(xù)數(shù)據(jù)存儲(chǔ)系統(tǒng)。2語(yǔ)言指導(dǎo)本指導(dǎo)描述了如何使用ProtocolBuffer語(yǔ)言來(lái)定義結(jié)構(gòu)化數(shù)據(jù)類型,包括.proto文件的語(yǔ)法和如何生成存取類。這是一份指導(dǎo)手冊(cè),一步步的例子使用文檔中的多種功能,查看入門指導(dǎo)(http:2定義一個(gè)消息類型waiting值類型waiting可選字段與缺省值waiting枚舉wait

15、ing使用其他消息類型waiting嵌套類型waiting更新一個(gè)數(shù)據(jù)類型waiting擴(kuò)展waiting包waiting定義服務(wù)waiting選項(xiàng)waiting生成你的類waiting3代碼風(fēng)格指導(dǎo)本文檔提供了.proto文件的代碼風(fēng)格指導(dǎo)。按照慣例,你將會(huì),你將會(huì)生成一些便于閱讀和一致的ProtocolBuffer定義文件。3.1消息與字段名使用駱駝風(fēng)格的大小寫命名,即單詞首字母大寫,來(lái)做消息名。使用GNU的全部小寫,使用下劃線分隔的方式定義字段名:messageSongServerRequestrequiredstringsong_name=1;使用這種命名方式得到的名字如下:C+:co

16、nststring&song_name().voidset_song_name(conststring&x).Java:publicStringgetSongName().publicBuildersetSongName(Stringv).3.2攻舉使用駱駝風(fēng)格做枚舉名,而用全部大寫做值的名字enumFooFIRST_VALUE=1;SECOND_VALUE=2;每個(gè)枚舉值最后以分號(hào)結(jié)尾,而不是逗號(hào)3.3服務(wù)如果你的.proto文件定義了RPC服務(wù),你可以使用駱駝風(fēng)格:serviceFooServicerpcGetSomething(FooRequest)returns(Foo

17、Response);)4編碼本文檔描述了ProtocolBuffer的串行化二進(jìn)制數(shù)據(jù)格式定義。你如果僅僅是在應(yīng)用中使用ProtocolBuffer,并不需要知道這些,但是這些會(huì)對(duì)你定義高效的格式有所幫助。4.1一個(gè)簡(jiǎn)單的消息waiting4.2基于128的Varintswaiting4.3消息結(jié)構(gòu)waiting更多的值類型waiting內(nèi)嵌消息waiting可選的和重復(fù)的元素waiting字段順序waiting5ProtocolBuffer基礎(chǔ):C+waitingProtocolBuffer基礎(chǔ):JavawaitingProtocolBuffer基礎(chǔ):Python本指南給Python程序員一

18、個(gè)快速使用的ProtocolBuffer的指導(dǎo)。通過(guò)一些簡(jiǎn)單的例子來(lái)在應(yīng)用中使用ProtocolBuffer,它向你展示了如何:定義.proto消息格式文件使用ProtocolBuffer編譯器使用Python的ProtocolBuffer編程接口來(lái)讀寫消息這并不是一個(gè)在Python中使用ProtocolBuffer的完整指導(dǎo)。更多細(xì)節(jié)請(qǐng)參考手冊(cè)信息,查看語(yǔ)言指導(dǎo)(API(為什么使用ProtocolBuffer?下面的例子"地址本"應(yīng)用用于讀寫人的聯(lián)系信息。每個(gè)人有name、ID、email,和聯(lián)系人電話號(hào)碼。如何串行化和讀取結(jié)構(gòu)化數(shù)據(jù)呢?有如下幾種問(wèn)題:使用Python的

19、pickle,這是語(yǔ)言內(nèi)置的缺省方法,不過(guò)沒(méi)法演化,也無(wú)法讓其他語(yǔ)言支持。你可以發(fā)明一種數(shù)據(jù)編碼方法,例如4個(gè)整數(shù)”12:323:67,這是簡(jiǎn)單而靈活的方法,不過(guò)你需要自己寫解析器代碼,且只適用于簡(jiǎn)單的數(shù)據(jù)。串行化數(shù)據(jù)到XML。這種方法因?yàn)榭勺x性和多種語(yǔ)言的兼容函數(shù)庫(kù)而顯得比較吸引人,不過(guò)這也不是最好的方法,因?yàn)閄ML浪費(fèi)空間是臭名昭著的,編碼解碼也很浪費(fèi)時(shí)間。而XMLDOM樹也是很復(fù)雜的。ProtocolBuffer提供了靈活、高效、自動(dòng)化的方法來(lái)解決這些問(wèn)題。通過(guò)ProtocolBuffer,只需要寫一個(gè).proto數(shù)據(jù)結(jié)構(gòu)描述文件,就可以編譯到幾種語(yǔ)言的自動(dòng)編碼解碼類。生成的類提供了se

20、tter和getter方法來(lái)控制讀寫細(xì)節(jié)。最重要的是ProtocolBuffer支持后期擴(kuò)展協(xié)議,而又確保舊格式可以兼容。哪里可以找到例子代碼源碼發(fā)行包中已經(jīng)包含了,在example'文件夾定義你的協(xié)議格式想要?jiǎng)?chuàng)建你的地址本應(yīng)用,需要開(kāi)始于一個(gè).proto文件。定義一個(gè).proto文件很簡(jiǎn)單:添加一個(gè)消息到數(shù)據(jù)結(jié)構(gòu),然后指定一個(gè)和一個(gè)類型到每一個(gè)字段,如下是本次例子使用的topackagetutorial;messagePersonrequiredstringname=1;requiredint32id=2;optionalstringemail=3;en

21、umPhoneTypeMOBILE=0;HOME=1;WORK=2;messagePhoneNumberrequiredstringnumber=1;optionalPhoneTypetype=2default=HOME;repeatedPhoneNumberphone=4;messageAddressBookrepeatedPersonperson=1;有如你所見(jiàn)的,語(yǔ)法類似于C+或Javao讓我們分塊理解他們。waiting編譯你的ProtocolBuffer現(xiàn)在已經(jīng)擁有了.proto文件,下一步就是編譯生成相關(guān)的訪問(wèn)類。運(yùn)行編譯器protoc編譯你的.proto文件。.如果還沒(méi)安裝編譯器

22、則下載并按照README的安裝。.運(yùn)行編譯器,指定源目錄和目標(biāo)目錄,定位你的.proto文件到源目錄,然后執(zhí)行protoc-I=$SRC_DIR-python_out=$DST_DIRto因?yàn)樾枰褂肞ython類,所以-python_out選項(xiàng)指定了特定的輸出語(yǔ)言。這個(gè)步驟會(huì)生成addressbook_pb2.py©目標(biāo)目錄。7.5ProtocolBufferAPI不像生成的C+和Java代碼,Python生成的類并不會(huì)直接為你生成存取數(shù)據(jù)的代碼。而是(有如你在addressbook_pb2.py見(jiàn)到的)生成消息描述、枚舉、和字段,還有一些神秘的空類,

23、每個(gè)對(duì)應(yīng)一個(gè)消息類型:classPerson(message.Message):_metaclass_=reflection.GeneratedProtocolMessageTypeclassPhoneNumber(message.Message):_metaclass_=reflection.GeneratedProtocolMessageTypeDESCRIPTION=_PERSON_PHONENUMBERDESCRIPTOR=_PERSONclassAddressBook(message.Message):_metaclass_=reflection.GeneratedProtocolM

24、essageTypeDESCRIPTOR=_ADDRESSBOOK這里每個(gè)類最重要的一行是_metaclass_=reflection.GeneratedProtocolMessageTyp國(guó)過(guò)Python的元類機(jī)制工作,你可以把他們看做是生成類的模板。在載入時(shí),GeneratedProtocolMessageType元類使用特定的描述符創(chuàng)建Python方法。隨后你就可以使用完整的功能了。最后就是你可以使用Person類來(lái)操作相關(guān)字段了。例如你可以寫:importaddressbook_pb2person=addressbook_pb2.Person()person.id=1234person

25、.name="JohnDoe"person.email="jdoe”phone=person.phone.add()phone.number="555-4321”phone.type=addressbook_pb2.Person.HOME需要注意的是這些賦值屬性并不是簡(jiǎn)單的增加新字段到Python對(duì)象,如果你嘗試給一個(gè).proto文件中沒(méi)有定義的字段賦值,就會(huì)拋出AttributeError異常,如果賦值類型錯(cuò)誤會(huì)拋出TypeError。在給一個(gè)字段賦值之前讀取會(huì)返回缺省值:person.no_such_field=1#raiseAttributeErr

26、orperson.id="1234"#raiseTypeError更多相關(guān)信息參考(枚舉枚舉在元類中定義為一些符號(hào)常量對(duì)應(yīng)的數(shù)字。例如常量addressbook_pb2.Person.WORK擁有值2。標(biāo)準(zhǔn)消息方法每個(gè)消息類包含一些其他方法允許你檢查和控制整個(gè)消息,包括:IsInitialized():檢查是否所有必須(required)字段都已經(jīng)被賦值了。_str_():返回人類可讀的消息表示,便于調(diào)試。CopyFrom(other_msg):使用另外一個(gè)消息的值來(lái)覆蓋本消息。Clear():清除所有元素的值,回到初識(shí)狀態(tài)。這些方法是通過(guò)接口Message實(shí)現(xiàn)的,更多消息

27、參考(7.5.3解析與串行化最后,每個(gè)ProtocolBuffer類有些方法用于讀寫消息的二進(jìn)制數(shù)據(jù)(*SerializeToString():串行化,并返回字符串。注意是二進(jìn)制格式而非文本。ParseFromString(data):解析數(shù)據(jù)。他們是成對(duì)使用的,提供二進(jìn)制數(shù)據(jù)的串行化和解析。另外參考消息API參考(NoteProtocolBuffer與面向?qū)ο笤O(shè)計(jì)ProtocolBuffer類只是用于存取數(shù)據(jù)的,類似于C+中的結(jié)構(gòu)體,他們并沒(méi)有在面向?qū)ο蠓矫孀龊芎玫脑O(shè)計(jì)。如果你想要給這些類添加更多的行為,最好的方法是包裝(wrap)o包裝同樣適合于復(fù)用別人寫好的.proto文件。這種情況下,

28、你可以把ProtocolBuffer生成類包裝的很適合于你的應(yīng)用,并隱藏一些數(shù)據(jù)和方法,暴露有用的函數(shù)等等。你不可以通過(guò)繼承來(lái)給自動(dòng)生成的類添加行為。這會(huì)破壞他們的內(nèi)部工作機(jī)制。7.6寫消息現(xiàn)在開(kāi)始嘗試使用ProtocolBuffer的類。第一件事是讓地址本應(yīng)用可以記錄聯(lián)系人的細(xì)節(jié)信息。想要做這些需要先創(chuàng)建聯(lián)系人實(shí)例,然后寫入到輸出流。這里的程序從文件讀取地址本,添加新的聯(lián)系人信息,然后寫回新的地址本到文件。#!/usr/bin/pythonimportaddressbook_pb2importsys#這個(gè)函數(shù)使用用戶輸入填充聯(lián)系人信息defPromptForAddress(person):p

29、erson.id=int(raw_input("EnterpersonIDnumber:")=raw_input("Entername:")email=raw_input("Enteremailaddress(blankfornone):")ifemail!="":person.email=emailwhileTrue:number=raw_input("Enteraphonenumber(orleaveblanktofinish):")ifnumber="&qu

30、ot;:breakphone_number=person.phone.add()phone_number.number=numbertype=raw_input("Isthisamobile,home,orworkphone?")iftype="mobile":phone_number.type=addressbook_pb2.Person.MOBILEeliftype="home":phone_number.type=addressbook_pb2.Person.HOMEeliftype="work":phone

31、_number.type=addressbook_pb2.Person.WORKelse:print"Unknownphonetype;leavingasdefaultvalue."#主函數(shù),從文件讀取地址本,添加新的聯(lián)系人,然后寫回到文件iflen(sys.argv)!=2:print"Usage:",sys.argv0,"ADDRESS_BOOK_FILE"sys.exit(-1)address_book=addressbook_pb2.AddressBook()讀取已經(jīng)存在的地址本try:f=open(sys.argv1,&qu

32、ot;fb")address_book.ParseFromString(f.read()f.close()exceptOSError:printsys.argv1+":Countopenfile.Creatinganewone."添加地址PromptFromAddress(address_book.person.add()寫入到文件f=open(sys.argv1,"wb")f.write(address_book.SerializeToString()f.close()7.7讀消息當(dāng)然,一個(gè)無(wú)法讀取的地址本是沒(méi)什么用處的,這個(gè)例子讀取剛才創(chuàng)建

33、的文件并打印所有信息#!/usr/bin/pythonimportaddressbook_pb2importsys#遍歷地址本中所有的人并打印出來(lái)defListPeople(address_book):forpersoninaddress_book.person:print"PersonID:",person.idprint"Name:",ifperson.HasField("email"):print"E-mail:",person.emailforphone_numberinperson.

34、phone:ifphone_number.type=addressbook_pb2.Person.MOBILE:print"Mobilephone#:",elifphone_number.type=addressbook_pb2.Person.HOME:print"Homephone#:",elifphone_number.type=addressbook_pb2.Person.WORK:print"Workphone#:",printphone_number.number#主函數(shù),從文件讀取地址本iflen(sys.argv)!=2

35、:print"Usage:",sys.argv0,"ADDRESS_BOOK_FILE"sys.exit(-l)address_book=addressbook_pb2.AddressBook()#讀取整個(gè)地址本文件f=open(sys.argv1,"rb")address_book.ParseFromString(f.read()f.close()ListPeople(address_book)擴(kuò)展ProtocolBuffer在你發(fā)不了代碼以后,可能會(huì)想要改進(jìn)ProtocolBuffer的定義。如果你想新的數(shù)據(jù)結(jié)構(gòu)向后兼容,而你的舊

36、數(shù)據(jù)可以向前兼容,那么你就找對(duì)了東西了,不過(guò)有些規(guī)則需要遵守。在新版本的ProtocolBuffer中:必須不可以改變已經(jīng)存在的標(biāo)簽的數(shù)字。必須不可以增加或刪除必須(required)字段。可以刪除可選(optional)或重復(fù)(repeated)字段。可以添加新的可選或重復(fù)字段,但是必須使用新的標(biāo)簽數(shù)字,必須是之前的字段所沒(méi)有用過(guò)的。這些規(guī)貝1(也有例夕卜(http:用。如果你遵從這些規(guī)則,舊代碼會(huì)很容易的讀取新的消息,并簡(jiǎn)單的忽略新的字段。而對(duì)舊的被刪除的可選字段也會(huì)簡(jiǎn)單的使用他們的缺省值,被刪除的重復(fù)字段會(huì)自動(dòng)為空。新的代碼也會(huì)透明的讀取舊的消息。然而,需要注意的是新的可選消息不會(huì)在舊的

37、消息中顯示,所以你需要使用has_嚴(yán)格的檢查他們是否存在,或者在.proto文件中提供一個(gè)缺省值。如果沒(méi)有缺省值,就會(huì)有一個(gè)類型相關(guān)的默認(rèn)缺省值:對(duì)于字符串就是空字符串;對(duì)于布爾型則是false;對(duì)于數(shù)字類型默認(rèn)為0。同時(shí)要注意的是如果你添加了新的重復(fù)字段,你的新代碼不會(huì)告訴你這個(gè)字段為空(新代碼)也不會(huì),也不會(huì)(舊代碼)包含has_標(biāo)志。高級(jí)使用ProtocolBuffer不僅僅提供了數(shù)據(jù)結(jié)構(gòu)的存取和串行化。查看PythonAPI參考(一個(gè)核心功能是通過(guò)消息類的映射(reflection)提供的。你可以通過(guò)它遍歷消息的所有字段,和管理他們的值。關(guān)于映射的一個(gè)很有用的地方是轉(zhuǎn)換到其他編碼,如X

38、ML或JSONo一個(gè)使用映射的更高級(jí)的功能是尋找同類型兩個(gè)消息的差異,或者開(kāi)發(fā)出排序、正則表達(dá)式等功能。使用你的創(chuàng)造力,還可以用ProtocolBuffer實(shí)現(xiàn)比你以前想象的更多的問(wèn)題。映射是通過(guò)消息接口提供的。waitingC+代碼生成waitingC+APIwaitingJava代碼生成waitingJavaAPIwaitingPython代碼生成本頁(yè)提供了Python生成類的相關(guān)細(xì)節(jié)。你可以在閱讀本文檔之前查看語(yǔ)言指導(dǎo)。Python的ProtocolBuffer實(shí)現(xiàn)與C+和Java的略有不同,編譯器只輸出構(gòu)建代碼的描述符來(lái)生成類,而由Python的元類來(lái)執(zhí)行工作。本文檔描述了元類開(kāi)始生效

39、以后的東西。ProtocolBuffer通過(guò)編譯器的"python_out=選項(xiàng)來(lái)生成Python的相關(guān)類。這個(gè)參數(shù)實(shí)際上是指定輸出的Python類放在哪個(gè)目錄下。編譯器會(huì)為每個(gè).proto文件生成一個(gè)對(duì)應(yīng)的.py文件。輸出文件名與輸入文件名相關(guān),不過(guò)有兩處修改:擴(kuò)展名.proto改為.py。路徑名的修改。如果你按照如下調(diào)用編譯器:protoc-proto_path=src-python_out=build/gensrc/tosrc/bar/to編譯器會(huì)自動(dòng)讀取兩個(gè).proto文件然后產(chǎn)生兩個(gè)輸出文件。在需要時(shí)編譯器會(huì)自動(dòng)創(chuàng)建目錄,不過(guò)python_out

40、指定的目錄不會(huì)自動(dòng)創(chuàng)建。需要注意的是,如果.proto文件名或路徑包含有無(wú)法在Python中使用的模塊名(如連字符),就會(huì)被自動(dòng)轉(zhuǎn)換為下劃線。所以文件to會(huì)變成foo_bar_pb2.py。Note在每個(gè)文件后綴的_pb2.py中的2代表ProtocolBuffer版本2。版本1僅在Google內(nèi)部使用,但是你仍然可以在以前發(fā)布的一些代碼中找到它。自動(dòng)版本2開(kāi)始,ProtocolBuffer開(kāi)始使用完全不同的接口了,從此Python也沒(méi)有編譯時(shí)類型檢查了,我們加上這個(gè)版本號(hào)來(lái)標(biāo)志Python文件名。包Python代碼生成根本不在乎包的名字。因?yàn)镻ython使用目錄名來(lái)做包

41、名。消息先看看一個(gè)簡(jiǎn)單的消息聲明:messageFoo。ProtocolBuffer編譯器會(huì)生成類Foo,它是tobuf.Message的子類。這個(gè)實(shí)體類,不含有虛擬方法。不像C+和Java,Python生成類對(duì)優(yōu)化選項(xiàng)不感冒;實(shí)際上Python的生成代碼已經(jīng)為代碼大小做了優(yōu)化。你不能繼承Foo的子類。生成類被設(shè)計(jì)不可以被繼承,否則會(huì)被打破一些設(shè)計(jì)。另外,繼承本類也是不好的設(shè)計(jì)。Python的消息類沒(méi)有特定的公共成員,而是定義接口,極其嵌套的字段、消息和枚舉類型。一個(gè)消息可以在另外一個(gè)消息中聲明,例如messageFoomessageBar在這種't#況下,Bar類

42、定義為Foo的一個(gè)靜態(tài)成員,所以你可以通過(guò)Foo.Bar來(lái)引用。字段對(duì)于消息類型中的每一個(gè)字段,都有對(duì)應(yīng)的同名成員簡(jiǎn)單字段如果你有一個(gè)簡(jiǎn)單字段(包括可選的和重復(fù)的),也就是非消息字段,你可以通過(guò)簡(jiǎn)單字段的方式來(lái)管理,例如foo字段的類型是int32,你可以:message.foo=123printmessage.foo注意設(shè)置foo的值,如果類型錯(cuò)誤會(huì)拋出TypeError。如果foo在賦值之前就讀取,就會(huì)使用缺省值。想要檢查是否已經(jīng)賦值,可以用HasField(),而清除該字段的值用ClearField()。例如:assertnotmessage.HasField("foo&quo

43、t;)message.foo=123assertmessage.HasField("foo")message.ClearField("foo")assertnotmessage.HasField("foo")簡(jiǎn)單消息字段消息類型工作方式略有不同。你無(wú)法為一個(gè)嵌入消息字段賦值。而是直接操作這個(gè)消息的成員。因?yàn)閷?shí)例化上層消息時(shí),其包含的子消息同時(shí)也實(shí)例化了,例如定義:messageFoooptionalBarbar=1;messagebaroptionalint32i=1;你不可以這么做,因?yàn)椴荒茏鱿㈩愋妥侄蔚馁x值:foo=Foo()foo.bar=Bar()#WRONG!而是可以直接對(duì)消息類型字段的成員賦值:foo=Foo()assertnotfoo.HasField("bar")foo.bar.i=1assertfoo.HasField("bar")注意簡(jiǎn)單的讀取消息類型字段的未賦值成員只不過(guò)是打印其缺省值

溫馨提示

  • 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。

評(píng)論

0/150

提交評(píng)論