轻全python3协议缓冲区的实现

lightprotobuf的Python项目详细描述


lightprotobuf

简介

lightprotobuf是一个完整的python 3协议缓冲区实现,如google所描述。

文档

要使用的主要类是lightprotobuf.message

它必须是您定义的每个消息的基类。其余部分遵循.proto设计:

此消息:

enum FooEnum {
   FIELD = 5;
   FIELD2 = 6;
}

message FooMsg {
   required int32 foo_field = 1;
   optional FooEnum foo_enum = 2;
   enum BarEnum {
      FIELD = 5;
      BAR = 6;
   }
   required BarEnum bar_enum = 3;
   repeated string foo_rep = 4;
   repeated int32 foo_pak = 5 [packed=true];
}

message BarMsg {
   required FooMsg.BarEnum bar_enum = 1;
}

在python中转换为:

from enum import IntEnum
from lightprotobuf import *
class FooEnum(IntEnum):
     FIELD = 5
     FIELD2 = 6

class FooMsg(Message):
     class BarEnum(IntEnum):
             FIELD = 5
             BAR = 6
     foo_field = Field(1, Int32, Field.REQUIRED, **{})
     bar_enum = Field(3, BarEnum, Field.REQUIRED, **{})
     foo_enum = Field(2, FooEnum, Field.OPTIONAL, **{})

class BarMsg(Message):
     bar_enum = Field(1, FooMsg.BarEnum, Field.REQUIRED, **{})

如您所见,字段遵循此模板

<name> = Field(<tag number>, <type>, Field.<REQUIRED|OPTIONEL|REPEATED>, **{<options as a dict (optional)>}

枚举是python的enum.IntEnum

嵌套类型是真正的python嵌套类型,就像在.proto中引用的那样

api

字段实际上通过描述符转换为属性。因此您可以轻松访问字段:

m = FooMsg()
m.foo_field = 5
m.foo_field # returns 5
m.foo_enum = 5 # Error because it expects a FooEnum object
m.foo_enum = FooEnum.FIELD # OK
m.bar_enum = FooMsg.BarEnum.BAR # OK

重复字段atc,如列表:

m.foo_rep = ["a string", "another"] # OK
li = m.foo_rep # Get a reference to the list
li.append("a string") # OK, append the string
li.append(b'a bytes') # TypeError because there is a check to avoid mistakes

注意:压缩字段可以解码压缩的数据,也可以解码多次出现的字段,例如测试用例:

class Repeated(Message):
        r = Field(1, Int32, Field.REPEATED, packed="True")
nb = [1,150,1,2,3,150]
b = io.BytesIO(b'\x0C\x08\x01\x08\x96\x01\x0A\x05\x01\x02\x03\x96\x01')
m = Repeated.from_stream(b)
self.assertEqual(list(m.r), nb)
# 0C (12) bytes following
# 08 = 1 << 3 | 0
# varints etc.
# 0A = 1 << 3 | 2
# 05 bytes following
# concatened varints etc.

为了对消息进行编码,lightprotobuf使用流对象:每个数据类型都有一个to_streamfrom_stream类方法。只需从消息中调用它即可对消息进行编码/解码:

import io
s = io.BytesIO()
Message.to_stream(s, m)
s.getvalue() # b'\x06\x08\x05\x10\x05\x18\x06'

m = FooMsg()
s = io.BytesIO(b'\x06\x08\x05\x10\x05\x18\x06')
m = Message.from_stream(s)

注意:如果缺少必需字段,则会引发fieldnotoptional异常

发行说明

1.0.b3

  • 警告:模块在顶层移动。使用导入lightprotobuf而不是从lightprotobuf导入lightprotobuf
  • 添加对重复字段(打包和未打包)的支持

1.0.b2

  • 删除description.rst,因为readme.rst的副本

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

推荐PyPI第三方库


热门话题
从log4j迁移到log4j2时发生java错误   java为什么我不能运行hello swing应用程序?   Java反射:按声明顺序获取字段和方法   java将日期设置为每周的第二天   在Java中使用包装器和随机森林分类器进行特征选择时出现weka错误   oop对随机生成的Java数字有问题   java使用PhoneNumberUtils检查联系人中是否存在号码。比较()   java无法在Tomcat 7(org.apache.catalina.LifecycleeException)上部署YouTrack   java无法添加自定义视图类   java如何从服务器端更改HttpServletRequest中的IP?   java GemFire 8.2.0集群使用缓存中的静态服务器列表。xml   运行google maps API v2约20分钟时出现java JNI错误   java在IntelliJ IDEA中创建一个可执行的jar