反序列化包含嵌套类型的protobuf描述符时出错

时间:2013-07-19 14:02:54

标签: python serialization protocol-buffers

我需要向我的服务器发送一个protobuf描述符,以便它可以用于序列化/反序列化包含嵌套类型的对象。我写了一个快速的例子来证明我的问题:

test.proto:

message A {
  message B {
    required string data = 1;
  }
  repeated B bs = 1;
}

test.py:

from descriptor_pb2 import DescriptorProto
from google.protobuf import descriptor,reflection,message

from test_pb2 import *

a = A()
b = a.bs.add()
b.data = "stuff"

d1 = a.DESCRIPTOR

dp1 = DescriptorProto()
d1.CopyToProto(dp1)

# dp1 serialized, sent over network, deserialized

d2 = descriptor.MakeDescriptor(dp1)

## This code fixes the problem
#for desc in dp1.nested_type:
#    d2.nested_types.append( descriptor.MakeDescriptor(desc) )
#d2.nested_types_by_name = dict((t.name, t) for t in d2.nested_types)
#    
#for f in dp1.field:
#    d2.fields_by_number[f.number].message_type = d2.nested_types_by_name[f.type_name.split('.')[-1]]
#
## This line cannot be run on the server side
#d2.fields[0].message_type._concrete_class = d1.fields[0].message_type._concrete_class 

reflection.ParseMessage(d1, a.SerializeToString())
reflection.ParseMessage(d2, a.SerializeToString())

当我运行此代码时,我在最后一行收到错误:

Traceback (most recent call last):
  File "test.py", line 29, in <module>
    reflection.ParseMessage(d2, a.SerializeToString())
  File "build\bdist.win32\egg\google\protobuf\reflection.py", line 168, in ParseMessage
    new_msg.ParseFromString(byte_str)
  File "build\bdist.win32\egg\google\protobuf\message.py", line 182, in ParseFromString
    self.MergeFromString(serialized)
  File "build\bdist.win32\egg\google\protobuf\internal\python_message.py", line 795, in MergeFromString
    if self._InternalParse(serialized, 0, length) != length:
  File "build\bdist.win32\egg\google\protobuf\internal\python_message.py", line 827, in InternalParse
    pos = field_decoder(buffer, new_pos, end, self, field_dict)
  File "build\bdist.win32\egg\google\protobuf\internal\decoder.py", line 523, in DecodeRepeatedField
    if value.add()._InternalParse(buffer, pos, new_pos) != new_pos:
  File "build\bdist.win32\egg\google\protobuf\internal\containers.py", line 216, in add
    new_element = self._message_descriptor._concrete_class(**kwargs)
AttributeError: 'NoneType' object has no attribute '_concrete_class'

我发现错误发生是因为当从反序列化的DescriptorProto复制时,descriptor.MakeDescriptor()没有完全复制所有嵌套类型,因此我在注释块中编写代码来补偿它。但是,最后一行使用对原始描述符中的类的引用,因此我不能在我的服务器上执行此操作。

我花了无数个小时试图解决这个问题,这是我系统中非常重要的一部分。任何帮助将不胜感激。

0 个答案:

没有答案