Posted on:
Last modified:
当我们的程序需要保存一些对象到硬盘上供下次运行时使用,或者需要和其他程序交换数据 的时候,需要把对象用某种方式编程二进制字符串然后保存到硬盘上或者发送出去,这种方 法我们一般称作序列化。序列化有很多不同的方法,一般考虑三个方面:
下面考察几种序列化的方法
考虑到需要定义接口规范,所以我们只考虑 thrift 和 protobuf 两种
Thrift 的缺点:
所以先淘汰了 thrift。我们选择 protobuf
protobuf 和 thrift 两个的用法都是先定义 IDL(接口)文件,然后由编译器编译生成对应的语言 的代码。对于 C++ 这样的编译语言来说问题不大,我们可以把 IDL 编译的过程放到 makefile 里面去,但是对于 Python 这种没有编译的动态语言就尴尬了。具体来说,IDL 文件是需要提交到代码仓库的,但是生成的 Python 代码需不需要呢?
所以我还是倾向于只向代码库中提交 *.proto
或者 *.thrift
源文件,而不提交编译过后的文件。
protobuf 现在有两个主流版本,显然 proto2 要被逐渐废弃,本文使用的是 proto3。
syntax = "proto3";
package foo.bar;
import "myproject/other_protos.proto";
message SearchRequest {
string query = 1;
int32 page_number = 2;
int32 result_per_page = 3;
enum Corpus {
UNIVERSAL = 0;
WEB = 1;
IMAGES = 2;
LOCAL = 3;
NEWS = 4;
PRODUCTS = 5;
VIDEO = 6;
}
Corpus corpus = 4;
}
message SearchResponse {
repeated Result result = 1;
}
message Result {
string url = 1;
string title = 2;
repeated string snippets = 3;
}
上面的结构和 C 语言的 struct 定义很像。
ParseFromString: 从字符串中解析 protobuf 对象。虽然这个方法名字中包含了 string,但是实际 上使用的是 bytes。
r = SearchResponse()
r.ParseFromString(data)
SerializeToString: 序列化成字符串。同样使用 bytes。
data = r.SerializeToString()
属性可以直接访问和设置,如果属性名或者类型出错会抛出异常。
repeated 类型的基础类型属性可以像一个数组一样访问,map 类型可以像字典一样访问。但是赋值 必须通过 append 和 extend 赋值,而不能直接赋值。
repeated 类型的 message 类型不能使用 append,而必须使用 add 或者 extend 方法。这样可以 确保 message 类型被拷贝进去。
© 2016-2022 Yifei Kong. Powered by ynotes
All contents are under the CC-BY-NC-SA license, if not otherwise specified.
Opinions expressed here are solely my own and do not express the views or opinions of my employer.
友情链接: MySQL 教程站