背景:
工作中遇到一个Python解析.proto文件的问题,这个问题涉及到protobuf文件之间的引用,即.proto文件A的message的其中一个字段,是.proto文件B中定义的message。
查阅了很多资料,大多是介绍如何处理单个文件的,故自行回顾整理如下。想直接看结果的小伙伴可以滑到末尾看重点。
目录:
- 准备.proto文件
- 环境配置
- 编译.proto文件
- 变量读取示例
准备.proto文件
本文示例共涉及3个.proto文件:
![](https://img.haomeiwen.com/i10801112/be732844188bbed2.png)
OrderTest.proto 文件:
这个文件引用了TimestampTest.proto文件。
OrderTest.proto 定义了一个Order message,message中的两个字段可以理解为商品名称name和商品相关的时间timestamp,其中timestamp的类型是TimestampTest.proto 中定义的message。
syntax = "proto3";
import "TimestampTest.proto";
package Ding;
message Order {
string name = 1;
OrderTime timestamp = 100;
}
TimestampTest.proto 文件:
这个文件引用了 google/protobuf/timestamp.proto 文件。
TimestampTest.proto 定义了一个OrderTime message,message中的两个字段可以理解为下单时间和收货时间。每个字段都是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 文件
这个文件可以从Git上找到,主要内容如下:
message Timestamp {
int64 seconds = 1;
int32 nanos = 2;
}
笔者最终要用的是 OrderTest.proto 中的 Order message。
环境配置
OS
笔者用的是 Windows 10
Python
笔者用的是 python 3.7.6,没有安装Python的小伙伴可以点击这里下载。
Protobuf
其实就是安装google.protobuf 这个依赖包,可以使用 pip install protobuf 进行安装。
安装完成后可以在python安装目录中的这里找到:\Lib\site-packages\google。
查看安装的protobuf是什么版本:进入\Lib\site-packages\google\protobuf目录,找到init.py文件。
![](https://img.haomeiwen.com/i10801112/c4dcedf1f7df7dbf.png)
![](https://img.haomeiwen.com/i10801112/ce77f0cd98263442.png)
Protoc
protoc,即protocol compiler,是.proto文件的编译器,它可以根据proto文件中的定义,生成某编程语言可用的代码。点击这里下载对应的protoc程序。
笔者是Windows系统,64位,并且pip install 的 protobuf是3.11.3版本,所以笔者下载的是protoc-3.11.3-win64.zip
下载完成后解压,把\protoc-3.11.3-win64\bin目录添加进path变量中。
查看protoc版本:![](https://img.haomeiwen.com/i10801112/c45c407b1da8fb1b.png)
编译.proto文件
打开cmd窗口,进入.proto文件所在目录,输入命令
protoc --python_out=. OrderTest.proto
protoc --python_out=. TimestampTest.proto
python_out:生成的文件适用于Python,python_out=.表示生成的文件放在当前文件夹,OrderTest.proto指明要操作哪个.proto文件。
没有报错说明命令执行成功,能看到在当前目录中多了一个 OrderTest_pb2.py 文件和TimestampTest_pb2.py 文件。![](https://img.haomeiwen.com/i10801112/7bee33ae5e450496.png)
注: 安装 protobuf 的时候,已经得到 google/protobuf/timestamp.proto 文件对应的Python 代码了,不需要再手动编译。代码也在这个 \Lib\site-packages\google\protobuf 目录下面,文件名称 timestamp_pb2.py。
变量读取示例
新建一个Python 项目,新建一个 example.py 文件,把 OrderTest_pb2.py 文件和 TimestampTest_pb2.py 文件复制粘贴到 example.py 文件所在目录。![](https://img.haomeiwen.com/i10801112/ea92e3842c1e4797.png)
在 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)
运行这个 example.py 文件,可以看到order变量已经赋值成功了:
![](https://img.haomeiwen.com/i10801112/d8ee43b96166c2ca.png)
划重点
如果遇到protobuf文件引用的情况,访问字段时必须一层一层访问,比如:
order.timestamp.receiveTime.seconds = 1583595823
order.timestamp.receiveTime.nanos = 794162000
这样就会报错:
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
报错如下:
![](https://img.haomeiwen.com/i10801112/936393e4896f02bb.png)
网友评论