背景:
工作中遇到一個(gè)Python解析.proto文件的問題,這個(gè)問題涉及到protobuf文件之間的引用妙黍,即.proto文件A的message的其中一個(gè)字段,是.proto文件B中定義的message崩溪。
查閱了很多資料笼才,大多是介紹如何處理單個(gè)文件的尾膊,故自行回顧整理如下媳危。想直接看結(jié)果的小伙伴可以滑到末尾看重點(diǎn)。
目錄:
- 準(zhǔn)備.proto文件
- 環(huán)境配置
- 編譯.proto文件
- 變量讀取示例
準(zhǔn)備.proto文件
本文示例共涉及3個(gè).proto文件:
OrderTest.proto 文件:
這個(gè)文件引用了TimestampTest.proto文件冈敛。
OrderTest.proto 定義了一個(gè)Order message待笑,message中的兩個(gè)字段可以理解為商品名稱name和商品相關(guān)的時(shí)間timestamp,其中timestamp的類型是TimestampTest.proto 中定義的message抓谴。
syntax = "proto3";
import "TimestampTest.proto";
package Ding;
message Order {
string name = 1;
OrderTime timestamp = 100;
}
TimestampTest.proto 文件:
這個(gè)文件引用了 google/protobuf/timestamp.proto 文件暮蹂。
TimestampTest.proto 定義了一個(gè)OrderTime message,message中的兩個(gè)字段可以理解為下單時(shí)間和收貨時(shí)間齐邦。每個(gè)字段都是google/protobuf/timestamp.proto 中定義的message類型椎侠。
syntax = "proto3";
import "google/protobuf/timestamp.proto";
package Ding;
message OrderTime {
google.protobuf.Timestamp placeTime = 1;
google.protobuf.Timestamp receiveTime = 2;
}
google/protobuf/timestamp.proto 文件
這個(gè)文件可以從Git上找到第租,主要內(nèi)容如下:
message Timestamp {
int64 seconds = 1;
int32 nanos = 2;
}
筆者最終要用的是 OrderTest.proto 中的 Order message措拇。
環(huán)境配置
OS
筆者用的是 Windows 10
Python
筆者用的是 python 3.7.6,沒有安裝Python的小伙伴可以點(diǎn)擊這里下載慎宾。
Protobuf
其實(shí)就是安裝google.protobuf 這個(gè)依賴包丐吓,可以使用 pip install protobuf 進(jìn)行安裝。
安裝完成后可以在python安裝目錄中的這里找到:\Lib\site-packages\google趟据。
查看安裝的protobuf是什么版本:進(jìn)入\Lib\site-packages\google\protobuf目錄券犁,找到init.py文件。
Protoc
protoc粘衬,即protocol compiler,是.proto文件的編譯器,它可以根據(jù)proto文件中的定義稚新,生成某編程語言可用的代碼勘伺。點(diǎn)擊這里下載對(duì)應(yīng)的protoc程序。
筆者是Windows系統(tǒng)褂删,64位飞醉,并且pip install 的 protobuf是3.11.3版本,所以筆者下載的是protoc-3.11.3-win64.zip
下載完成后解壓屯阀,把\protoc-3.11.3-win64\bin目錄添加進(jìn)path變量中缅帘。
查看protoc版本:編譯.proto文件
打開cmd窗口,進(jìn)入.proto文件所在目錄难衰,輸入命令
protoc --python_out=. OrderTest.proto
protoc --python_out=. TimestampTest.proto
python_out:生成的文件適用于Python钦无,python_out=.表示生成的文件放在當(dāng)前文件夾,OrderTest.proto指明要操作哪個(gè).proto文件召衔。
沒有報(bào)錯(cuò)說明命令執(zhí)行成功铃诬,能看到在當(dāng)前目錄中多了一個(gè) OrderTest_pb2.py 文件和TimestampTest_pb2.py 文件。注: 安裝 protobuf 的時(shí)候苍凛,已經(jīng)得到 google/protobuf/timestamp.proto 文件對(duì)應(yīng)的Python 代碼了趣席,不需要再手動(dòng)編譯。代碼也在這個(gè) \Lib\site-packages\google\protobuf 目錄下面醇蝴,文件名稱 timestamp_pb2.py宣肚。
變量讀取示例
新建一個(gè)Python 項(xiàng)目,新建一個(gè) example.py 文件悠栓,把 OrderTest_pb2.py 文件和 TimestampTest_pb2.py 文件復(fù)制粘貼到 example.py 文件所在目錄霉涨。在 example.py 文件中輸入代碼:
import OrderTest_pb2 as Order_Message
# create an Order instance
order = Order_Message.Order()
order.name = "ProductName"
order.timestamp.placeTime.seconds = 1583484823
order.timestamp.placeTime.nanos = 794162000
order.timestamp.receiveTime.seconds = 1583595823
order.timestamp.receiveTime.nanos = 794162000
print(order)
運(yùn)行這個(gè) example.py 文件,可以看到order變量已經(jīng)賦值成功了:劃重點(diǎn)
如果遇到protobuf文件引用的情況惭适,訪問字段時(shí)必須一層一層訪問笙瑟,比如:
order.timestamp.receiveTime.seconds = 1583595823
order.timestamp.receiveTime.nanos = 794162000
這樣就會(huì)報(bào)錯(cuò):
import OrderTest_pb2 as Order_Message
import TimestampTest_pb2 as Order_Timestamp
timestamp = Order_Timestamp.OrderTime()
timestamp.placeTime.seconds = 1583484823
timestamp.receiveTime.seconds = 1583595823
# create an Order instance
order = Order_Message.Order()
order.timestamp = timestamp
報(bào)錯(cuò)如下: