protobuf 安装
protobuf 分为 2 和 3
- protoc 下载地址 需要根据自己平台下载不同版本(windows 就下载下面这个)
- 加入环境变量
- 测试一下
protoc --version
pip install protobuf
python 需要安装模块
protobuf 常见数据类型
这里列举了一些常用的数据类型
类型 | 说明 |
---|---|
string | 字符串类型,要求utf-8或7-bit与ascii编码的字符串 |
bytes | 比特类型 |
bool | 布尔类型 |
int32 | 32位整形 |
int64 | 64位整形 |
float | 浮点类型 |
repeated | 数组(列表) |
map | map(字典类型) |
protobuf 特殊字符
类型 | 说明 |
---|---|
package | 包名 |
syntax | Protobuf版本 |
service | 定义服务 |
rpc | 定义服务中方法 |
stream | 定义的方法传输为流传输 |
message | 定义消息体 message User{} |
extend | 拓展消息体 extend User{} |
import | 导入插件 |
// | 注释 |
实例
下面是一个完整的 Demo 例子
流程:
- 先配置好 proto 文件
- 终端下执行
protoc --python_out=./ addressbook.proto
得到 pb2.py 文件 - 编写测试 python 代码, 执行效果如下
当然也可以用下面方法编译 pb 文件
protoc --descriptor_set_out=./addressbook.pb ./addressbook.proto
syntax = "proto3";
package test;
message AddressBook {
repeated Person people = 1;
}
message Person {
string name = 1;
int32 id = 2;
string email = 3;
bool work_status = 4;
repeated PhoneNumber phones = 5;
repeated Money money = 6;
repeated string girlfriend = 7;
MyMessage maps = 8;
bytes byte=9;
}
message PhoneNumber {
string number = 1;
PhoneType type = 2;
}
message Money {
float ch = 1;
float us = 2;
}
enum PhoneType {
MOBILE = 0;
HOME = 1;
WORK = 2;
}
message MyMessage {
map<int32, int32> mapfield = 1;
}
#! /usr/bin/env python
from protobuf import addressbook_pb2
# 实例化对象
address_book = addressbook_pb2.AddressBook()
def Serialize_To_String():
person = address_book.people.add()
person.id = 1
person.name = "Zok"
person.email = "362416272@qq.com"
person.work_status = True
# person_money = person.money.add()
# person_money.us = 1000
# person_money.ch = 2000
# 也可以直接写
person.money.add(ch=2000, us=1000)
person.money.add(ch=3000, us=4000)
person.girlfriend.append('Baby')
person.girlfriend.extend(["Luci", "CoCo"])
phone_number = person.phones.add()
phone_number.number = "13999999999"
phone_number.type = addressbook_pb2.MOBILE
maps = person.maps
maps.mapfield[1] = 1
maps.mapfield[2] = 2
person.byte = bytes('我是吴彦祖', encoding='utf-8')
# 序列化
serializeToString = address_book.SerializeToString()
print(serializeToString, type(serializeToString))
with open('addressBook.bin', 'wb') as f:
f.write(serializeToString)
address_book.ParseFromString(serializeToString)
def Parse_From_String():
with open('addressBook.bin', 'rb') as f:
address_book.ParseFromString(f.read()) # 读取
for person in address_book.people:
msg = """
id: {}
name: {}
email: {}
work_status: {}""".format(person.id, person.name, person.email, person.work_status)
print(msg)
for m in person.money: # 数组遍历输出,
print(m.ch, m.us)
for phone_number in person.phones: # 遍历多个号码
print(phone_number.number, phone_number.type)
for key in person.maps.mapfield: # 遍历 map 字典
print(key, person.maps.mapfield[key])
for girl in person.girlfriend:
print(girl)
print('byte:', person.byte.decode()) # byte 类型编码
if __name__ == '__main__':
Serialize_To_String()
Parse_From_String()
反序列化
在我们没有拿到头文件的时候,我们只能查看无key状态下的值,以python为例,查看方法如下
import subprocess
def decode(data):
process = subprocess.Popen([r'D:\othter\protoc-3.15.6-win64\bin\protoc.exe', '--decode_raw'],
stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
output = error = None
try:
output, error = process.communicate(data)
except OSError:
pass
finally:
if process.poll() != 0:
process.wait()
return output
with open('addressBook.bin', 'rb') as f:
data = f.read() # 读取
print(str(decode(data), encoding="utf-8"))
想要彻底还原的话,需要找到配置文件,或者仿造配置文件