支持数据类的协议缓冲区数据类型的python实现

pure-protobuf的Python项目详细描述


纯协议

协议缓冲区的python实现。

构建状态coverage statuspypi-downloadspypi–versionpypi–pythonlicense

数据类

pure protobuf允许您利用标准的dataclasses模块来定义消息类型。对于新项目,它比传统接口更受欢迎。dataclasses接口在python 3.6及更高版本中可用。

旧式接口已弃用,但仍可以通过pure\u protobuf.legacy

本指南介绍如何使用纯protobuf来构造数据。它试图遵循标准开发人员指南。它还假设您熟悉协议缓冲区。

定义消息类型

让我们看看这个简单的例子。下面是它在proto3语法中的样子:

syntax="proto3";messageSearchRequest{stringquery=1;int32page_number=2;int32result_per_page=3;}

这就是用纯protobuf定义它的方式:

# Python 3.6+fromdataclassesimportdataclassfrompure_protobuf.dataclasses_importfield,messagefrompure_protobuf.typesimportint32@message@dataclassclassSearchRequest:query:str=field(1,default='')page_number:int32=field(2,default=int32(0))result_per_page:int32=field(3,default=int32(0))assertSearchRequest(query='hello',page_number=int32(1),result_per_page=int32(10),).dumps()==b'\x0A\x05hello\x10\x01\x18\x0A'

请记住,@messagedecorator应该始终保持在@dataclasses之上。

序列化

每个用@消息包装的类都会附加两个方法:

  • dumps()->;字节将消息序列化为字节字符串
  • 转储(io:io)将消息序列化为类似文件的对象

反序列化

每个用@message包装的类都会附加两个类方法:

  • 加载(字节)->;t消息从字节字符串反序列化消息
  • 加载(io:io)->;t消息从类似文件的对象反序列化消息

这些方法也可以作为pu中的独立函数使用关于protobuf.dataclasses

  • 加载(cls:type[t],io:io)->;t
  • 加载(cls:type[t],bytes懔bytes)->;t

指定字段类型

pure protobuf中,类型由类型提示指定。支持原生pythonfloatstrbytesbool类型。由于其他协议缓冲区类型不作为本机python类型存在,因此包使用newtype来定义它们。它们可以通过pure_protobuf.types获得,并以相同的方式命名。

分配字段号

字段号是通过字段的元数据参数提供的:字段(…,metadata={'number':number})。但是,为了提高可读性并保存一些字符,pure protobuf提供了一个助手函数pure protobuf.dataclasses\field它接受字段号作为第一个位置参数并将其传递给标准的字段函数。

指定字段规则

键入.list键入.iterable批注自动转换为重复字段。标量数字类型的重复字段默认使用压缩编码:

# Python 3.6+fromdataclassesimportdataclassfromtypingimportListfrompure_protobuf.dataclasses_importfield,messagefrompure_protobuf.typesimportint32@message@dataclassclassMessage:foo:List[int32]=field(1,default_factory=list)

也可以用typing.optional包装字段类型。如果none被分配给一个可选字段,则在序列化过程中将跳过该字段。

默认值

在纯protobuf中,开发人员有责任处理默认值。如果编码的消息不包含特定元素,则相应的字段保持未分配状态。这意味着字段的标准默认默认工厂参数正常工作:

# Python 3.6+fromdataclassesimportdataclassfromtypingimportOptionalfrompure_protobuf.dataclasses_importfield,messagefrompure_protobuf.typesimportint32@message@dataclassclassFoo:bar:int32=field(1,default=42)qux:Optional[int32]=field(2,default=None)assertFoo().dumps()==b'\x08\x2A'assertFoo.loads(b'')==Foo(bar=42)

事实上,模式qux:optional[int32]=field(2,default=none)非常常见,因此有一个方便的函数optional\u field来定义默认值为none的optional字段:

# Python 3.6+fromdataclassesimportdataclassfromtypingimportOptionalfrompure_protobuf.dataclasses_importoptional_field,messagefrompure_protobuf.typesimportint32@message@dataclassclassFoo:qux:Optional[int32]=optional_field(2)assertFoo().dumps()==b''assertFoo.loads(b'')==Foo(qux=None)

枚举

支持标准类的子类:

# Python 3.6+fromdataclassesimportdataclassfromenumimportIntEnumfrompure_protobuf.dataclasses_importfield,messageclassTestEnum(IntEnum):BAR=1@message@dataclassclassTest:foo:TestEnum=field(1)assertTest(foo=TestEnum.BAR).dumps()==b'\x08\x01'assertTest.loads(b'\x08\x01')==Test(foo=TestEnum.BAR)

使用其他消息类型

嵌入消息的定义方式与普通数据类相同:

# Python 3.6+fromdataclassesimportdataclassfrompure_protobuf.dataclasses_importfield,messagefrompure_protobuf.typesimportint32@message@dataclassclassTest1:a:int32=field(1,default=0)@message@dataclassclassTest3:c:Test1=field(3,default_factory=Test1)assertTest3(c=Test1(a=int32(150))).dumps()==b'\x1A\x03\x08\x96\x01'

众所周知的消息类型

pure_protobuf.google还提供了以下已知消息类型的内置定义

<表><广告>注释纯protobuf.types.google.proto< /广告><正文>日期时间 时间戳时间戳时间增量持续时间 持续时间 键入.any任何任意

它们是自动处理的,您无需执行任何操作,只需在键入提示时正常使用它们:

# Python 3.6+fromdataclassesimportdataclassfromdatetimeimportdatetimefromtypingimportOptionalfrompure_protobuf.dataclasses_importfield,message@message@dataclassclassTest:timestamp:Optional[datetime]=field(1,default=None)

任何" rel="nofo允许">任何

由于纯protobuf无法下载或解析.proto定义,因此它提供了一个有限的消息类型实现。也就是说,您仍然必须以通常的方式定义所有消息类。然后,纯protobuf将能够导入并实例化编码值:

# Python 3.6+fromdataclassesimportdataclassfromtypingimportAny,Optionalfrompure_protobuf.dataclasses_importfield,messagefrompure_protobuf.types.googleimportTimestamp@message@dataclassclassMessage:value:Optional[Any]=field(1)# Here `Timestamp` is used just as an example, in principle any importable user type works.message=Message(value=Timestamp(seconds=42))assertMessage.loads(message.dumps())==message

传统接口

对于Python2用户,传统接口已被弃用并保持在"维护模式"。总有一天它会被移走的。新项目应强烈考虑使用数据类。

假设您有以下定义:

syntax="proto3";messageSearchRequest{stringquery=1;int32page_number=2;int32result_per_page=3;}
0

这是创建消息并将其序列化的方法:

syntax="proto3";messageSearchRequest{stringquery=1;int32page_number=2;int32result_per_page=3;}
1

必需字段

若要添加缺少的字段,应将一个附加的标志参数传递给添加字段如下:

syntax="proto3";messageSearchRequest{stringquery=1;int32page_number=2;int32result_per_page=3;}
2

如果不填写所需字段,则在序列化期间将引发valueerror

重复字段

syntax="proto3";messageSearchRequest{stringquery=1;int32page_number=2;int32result_per_page=3;}
3

重复字段的值可以是任何iterable对象。加载的值将始终是列表

压缩重复字段

syntax="proto3";messageSearchRequest{stringquery=1;int32page_number=2;int32result_per_page=3;}
4

嵌入消息

syntax="proto3";messageSearchRequest{stringquery=1;int32page_number=2;int32result_per_page=3;}
5

要创建嵌入字段,请用embeddedmessage包装内部类型

syntax="proto3";messageSearchRequest{stringquery=1;int32page_number=2;int32result_per_page=3;}
6

数据类型

<表><广告>键入巨蟒说明 < /广告><正文>uvarintint无符号整数(可变长度)变量int有符号整数(可变长度)boolbool布尔型fixed64字节8字节字符串uint64intC 64位无符号长 int64intC 64位float64浮点数cdoublefixed32字节4字节字符串uint32intC 32位无符号整数int32intC 32位intfloat32浮点数Cfloat字节字节字节字符串unicodestrUnicode字符串

一些技巧

流式消息

协议缓冲区格式不是自限定的。但您可以用embeddedmessage包装您的消息类型,并按顺序写入或读取消息。

添加字段链接

添加字段返回消息类型本身,因此您可以这样做:

syntax="proto3";messageSearchRequest{stringquery=1;int32page_number=2;int32result_per_page=3;}
7

欢迎加入QQ群-->: 979659372 Python中文网_新手群

推荐PyPI第三方库


热门话题
jenkins在java代码的csv中使用前导零传递数字   终止java应用程序javaw。exe eclipse   java平均字长。文本   java在事务中关闭连接时会发生什么?   java如何为rich faces extendedDatatable启用可调整大小的列?   SpringJavaWebApp头nosniff不适合js和css文件   Java:抛出异常   java获取拒绝ArrayList中存在的用户名的代码。   关于编写JNDI服务提供者的java教程   java Android emulator电子书示例已停止   java如何防止双向关系中的循环   在Java中,如何将接口的实现作为变量传递给方法?   java有没有办法通过注释来监听CoreNLP处理的进度?   java Eclipse错误:导入项目时“无法读取项目描述文件”   java为什么findViewById返回null?