我需要向我的服务器发送一个 protobuf 描述符,以便它可以用于序列化/反序列化包含嵌套类型的对象。我写了一个简单的例子来演示我的问题:
测试原型:
message A {
message B {
required string data = 1;
}
repeated B bs = 1;
}
测试.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'
我发现发生错误是因为descriptor.MakeDescriptor()从反序列化的DescriptorProto复制时没有完全复制所有嵌套类型,所以我在注释块中编写了代码来弥补它。但是,最后一行使用对原始描述符中的类的引用,所以我不能在我的服务器上这样做。
我花了无数个小时试图解决这个问题,它是我系统中非常重要的一部分。任何帮助将不胜感激。