一、前言
-
Protobuf是一種輕便高效的結(jié)構(gòu)化數(shù)據(jù)存儲(chǔ)格式,可以用于結(jié)構(gòu)化數(shù)據(jù)序列化,很適合做數(shù)據(jù)存儲(chǔ)或 RPC 數(shù)據(jù)交換格式。它可用于通訊協(xié)議、數(shù)據(jù)存儲(chǔ)等領(lǐng)域的語(yǔ)言無(wú)關(guān)、平臺(tái)無(wú)關(guān)、可擴(kuò)展的序列化結(jié)構(gòu)數(shù)據(jù)格式。
-
可以簡(jiǎn)單理解為,是一種跨語(yǔ)言、跨平臺(tái)的數(shù)據(jù)傳輸格式。與json的功能類(lèi)似,但是無(wú)論是性能,還是數(shù)據(jù)大小都比json要好很多。
-
protobuf的之所以可以跨語(yǔ)言,就是因?yàn)閿?shù)據(jù)定義的格式為.proto格式,需要基于protoc編譯為對(duì)應(yīng)的語(yǔ)言。
二、效果
既然說(shuō)到了性能,還是數(shù)據(jù)大小都比json要好很多。那么我們不如來(lái)用一個(gè)例子了解一下具體展現(xiàn)在哪里。這同一個(gè)數(shù)據(jù)經(jīng)過(guò)Protobuf和Json格式轉(zhuǎn)換后的數(shù)據(jù)大小??梢灾庇^的看到Protobuf足足少了四分之三。
三、教程
1)安裝
protobuf下載地址
我是windows所以就選擇了windows的包
將protoc-23.1-win64.zip解壓后打開(kāi)該目錄的bin目錄,復(fù)制路徑
打開(kāi)電腦的環(huán)境變量設(shè)置,在系統(tǒng)變量下面選擇Path變量編輯
新建一個(gè),然后將復(fù)制的路徑粘貼到下面
在命令行敲一下下面命令查看是否可以正常調(diào)用
protoc --version
然后再解壓protobuf-23.1.zip文件,找到python
)
python目錄打開(kāi)cmd將下面三條命令敲入(pip的protobuf和下載的protobuf版本最好一致)–要在當(dāng)前目錄下的cmd噢
pip install protobuf
python setup.py build
python setup.py install
cmd打開(kāi)python可以正常輸入下面命令就代表安裝成功了。
from google.protobuf.internal import builder
2)使用
一個(gè)大概流程圖
1.創(chuàng)建.proto文件
根據(jù)流程圖,我們第一步是創(chuàng)建一個(gè).proto文件
2.proto語(yǔ)法
既然知道這是一個(gè)語(yǔ)法文件,那么里面肯定是要寫(xiě)一些語(yǔ)法在里面的。
這些語(yǔ)法是相當(dāng)于一個(gè)和使用者的約定,約定這些字段是這種語(yǔ)法定義的結(jié)構(gòu)。(這里只是基礎(chǔ)例子寫(xiě)的語(yǔ)法,具體的可以看文章gRPC之proto語(yǔ)法)
//第一行的含義是使用的是proto3的語(yǔ)法,如果沒(méi)有這句,則默認(rèn)使用proto2;
syntax = "proto3";
/*Person定義有三個(gè)承載消息的屬性,每一個(gè)被定義在Person 消息體中的字段,都是由數(shù)據(jù)類(lèi)型和屬性名稱組成。
里面的1,2,3是代表了編號(hào),protobuf為了節(jié)省空間,使用了編號(hào)來(lái)代替字段名,只有服務(wù)器和客戶端擁有同樣的proto語(yǔ)法文件才可以知道正確的字段名
不然解析出來(lái)的也是1,2,3為代表的結(jié)果
*/
message Person {
int32 id = 1;
string name = 2;
message Iphone {
string number = 1;
}
//repeated: 這個(gè)屬性代表了可以重復(fù)增加,就相當(dāng)于往List數(shù)組增加數(shù)據(jù)
repeated Iphone phones = 3;
}
message totalPerson{
repeated Person person = 1;
}
3.protoc.exe文件編譯.proto語(yǔ)法文件
在cmd輸入下面命令,example.proto是你寫(xiě)的.proto語(yǔ)法文件。
protoc --python_out=. example.proto
然后會(huì)在同級(jí)目錄下出現(xiàn)example_pb2.py文件
4.序列化
既然得到了example_pb2.py文件,那我們可以開(kāi)始嘗試序列化一份數(shù)據(jù)了。
先創(chuàng)建一份main.py文件,通過(guò)定義好的example_pb2.py文件語(yǔ)法來(lái)定義數(shù)據(jù)(實(shí)則是根據(jù).proto文件來(lái)定義),然后進(jìn)行一個(gè)序列化操作(使用SerializeToString)。
import example_pb2
# 從生成的example_pb2導(dǎo)入totalPerson(相當(dāng)于初始化對(duì)象)
result_pro = example_pb2.totalPerson()
# 從語(yǔ)法文件可以看到totalPerson中有repeated就代表person是可以被add多個(gè)的,我們這里就新增一個(gè)就好了;
person_message = result_pro.person.add()
# person被初始化后,就可以定義里面的屬性了
person_message.id = 1
person_message.name = "laowang"
# 基礎(chǔ)屬性定義完后,還有一個(gè)復(fù)合屬性phones,這里對(duì)他進(jìn)行一個(gè)新增初始化
phone = person_message.phones.add()
# 定義對(duì)象屬性
phone.number="123456"
# 這里是將定義好的數(shù)據(jù)進(jìn)行一個(gè)序列化操作
result=result_pro.SerializeToString()
print(result)
print("Protobuf: ", result.__sizeof__())
# 這里是將定義好的數(shù)據(jù)進(jìn)行一個(gè)序列化操作并且存入到bin文件
with open("my_example.bin", "wb") as f:
f.write(result)
5.反序列化
上圖可以看到成功序列化數(shù)據(jù)出來(lái)了,我們現(xiàn)在則要對(duì)保存的bin文件進(jìn)行反序列化
- 先通過(guò)有proto語(yǔ)法文件的反序列化(使用ParseFromString)
import example_pb2
# 從生成的example_pb2導(dǎo)入totalPerson(相當(dāng)于初始化對(duì)象)
result_pro = example_pb2.totalPerson()
with open("my_example.bin", "rb") as f:
result_pro.ParseFromString(f.read())
print(result_pro)
可以看到很好的還原出來(lái)了我們定義并且想要的數(shù)據(jù)格式。接下來(lái)我們看看json類(lèi)似的數(shù)據(jù)格式與之對(duì)比
- 無(wú)proto語(yǔ)法文件的反序列化
如果沒(méi)有語(yǔ)法文件呢,不用急,protobuf給了我們這樣一個(gè)工具可以幫助我們除了鍵名基本還原出來(lái)。(在my_example.bin同級(jí)目錄下打開(kāi)cmd輸入下面命令)
protoc --decode_raw < my_example.bin
可以得到下面的數(shù)據(jù)結(jié)構(gòu),對(duì)比上面除了鍵名不同其他都是一樣的,這就是protobuf對(duì)于鍵名不是很敏感的原因,他更敏感我們上面注釋說(shuō)的編號(hào)。這里展現(xiàn)的就是我們之前給鍵名定義的編號(hào)。
所以如果想要復(fù)刻只需要自己重新寫(xiě)一個(gè)proto語(yǔ)法文件,對(duì)照著編號(hào)結(jié)構(gòu),重新起一個(gè)鍵名進(jìn)行生成_pb2.py文件去達(dá)到序列化相同的數(shù)據(jù)結(jié)構(gòu)。
新建一個(gè)myprotobuf.proto語(yǔ)法文件,把鍵名全部換了(圖方便相當(dāng)于根據(jù)上圖的結(jié)果來(lái)模擬一個(gè).proto語(yǔ)法結(jié)構(gòu))
syntax = "proto3";
message newPerson {
int32 newid = 1;
string newname = 2;
message newIphone {
string newnumber = 1;
}
repeated newIphone newphones = 3;
}
message newtotalPerson{
repeated newPerson newperson = 1;
}
然后編譯它生成myprotobuf_pb2.py
protoc --python_out=. myprotobuf.proto
修改main.py文件調(diào)用,這里還是讀取我們上次序列化數(shù)據(jù)的bin文件
import myprotobuf_pb2
# 從生成的example_pb2導(dǎo)入totalPerson(相當(dāng)于初始化對(duì)象)
result_pro = myprotobuf_pb2.newtotalPerson()
# 反序列化
with open("my_example.bin", "rb") as f:
result_pro.ParseFromString(f.read())
print(result_pro)
可以看到成功反序列化出來(lái)了數(shù)據(jù)文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-763121.html
四、借鑒
什么是protobuf
gRPC之proto語(yǔ)法
JS逆向-Protobuf逆向解析文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-763121.html
到了這里,關(guān)于Protobuf協(xié)議初級(jí)詳解(python使用)從安裝到序列化-反序列化的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!