#protobuf #prost #pyo3

pyo3-prost

在Python中使用Rust protobuf结构体

2个不稳定版本

0.2.0 2021年7月11日
0.1.0 2021年7月9日

#1140 in 过程宏

MIT 许可协议

9KB
112

pyo3-prost

pyo3-prost将Rust protobuf结构体暴露给Python。

文档 []

# A simple decoding benchmark
Python:  14.008996680990094
Rust  :  0.5708326659951126

# A simple encoding benchmark
Python:  8.68384731200058
Rust  :  0.3029898940003477

===========
PythonTweet
===========
b'\n\x11Hi this is a text\x10\xfb\x99K"\x1b\n\x03Who\x12\x14https://example.com/*\x06@trump*\x06@obama'
===========
  RustTweet
===========
b'\n\x11Hi this is a text\x10\xfb\x99K"\x1b\n\x03Who\x12\x14https://example.com/*\x06@trump*\x06@obama'

您只需要在prost或tonic构建中添加一行

.type_attribute(".", "#[::pyo3_prost::pyclass_for_prost_struct]")

即可。

预期用途是当您的Python项目锁定为Protobuf时,您希望将部分迁移到Rust的本地模块。Python protobuf对象无法在Rust侧轻松处理。对于转换,Python protobuf对象应序列化和反序列化为Rust protobuf对象。使用pyo3-prost,您可以从Python中将字节解码为Rust结构体,并将其传递给本地模块。

工作原理

派生宏 pyclass_for_prost_struct 将添加

  1. #[pyclass] 到prost生成的结构体
  2. #[pyo3(get, set)] 为每个字段(除了oneof字段)。
  3. #[pymethods]encode() -> &PyBytesdecode(&PyBytes) -> Selfdecode_merge(&mut self, &PyBytes)
  4. #[pyproto]__str____repr__ 以便于检查。
  • 获取器和设置器支持嵌套结构。
  • encode_slow 以这种方式命名是因为它目前通过将数据序列化到 Rust 缓冲区并将字节复制到 Python 内存中实现的。

示例

  1. 转到 examples/proto-gen 并运行 cargo run。这将创建 examples/rupy_proto/src/app.rs
  2. 转到 examples/rupy_proto 并运行 cargo build --release
  3. examples/rupy_proto/target/release/librupy_proto.so 移动到 examples/rupy_proto/rupy_proto.so
  4. 运行基准测试 cd examples/rupy_proto && PYTHONPATH=. python bench.py

限制(目前)

访问数值字段速度快。但是,对重复、映射或消息字段的每次访问都可能返回一个克隆的 Python 对象。例如,obj.list_field.clear() 只会清除返回的副本,而实际值保持不变。

没有为 oneof 字段提供获取器/设置器。

稍后我将为这些情况添加自定义获取器/设置器。

依赖项

~1.5MB
~36K SLoC