6
votes

I am using dynamic reflection functionality of python protobuf v2.6.1, and have a function like below:

# initilization code

        des_db_ = descriptor_database.DescriptorDatabase()
        des_pool_ = descriptor_pool.DescriptorPool(des_db_)


        fdp = descriptor_pb2.FileDescriptorProto.FromString(
            a_pb_module.DESCRIPTOR.serialized_pb)
        des_db_.Add(fdp)


def unpack_PB_msg(type_name, pb_msg_str)
        factory = message_factory.MessageFactory(des_pool_)
        msg_class = factory.GetPrototype(des_pool_.FindMessageTypeByName(type_name))

        pb_msg = msg_class()
        pb_msg.ParseFromString(pb_msg_str)

       return pb_msg

But following client code will fail

hello = Hello_msg()
hello_str = hello.SerializeToString()
hello2 = unpack_PB_msg(Hello_msg.DESCRIPTOR.full_name, hello_str)

hello3 = Hello_msg()
hello3.CopyFrom(hello2)# failed here!!!

The error message is:

hello3.CopyFrom(hello2)
  File "C:\Localdata\Python27\lib\site-packages\google\protobuf\message.py", line 119, in CopyFrom
    self.MergeFrom(other_msg)
  File "C:\Localdata\Python27\lib\site-packages\google\protobuf\internal\python_message.py", line 971, in MergeFrom
    "expected %s got %s." % (cls.__name__, type(msg).__name__))
TypeError: Parameter to MergeFrom() must be instance of same class: expected Hello_msg got Hello_msg.

It seems CopyFrom fails because isinstance fails.

  def MergeFrom(self, msg):
    if not isinstance(msg, cls):
      raise TypeError(
          "Parameter to MergeFrom() must be instance of same class: "
          "expected %s got %s." % (cls.__name__, type(msg).__name__))

When print data type of hello2 and hello3, it seems they are different.

hello2 : <class 'Hello_msg'>
hello3 : <class 'a_pb_module.Hello_msg'>

Is this a protobuf bug? or I made something wrong?

1
cls isn't defined in MergeFrom or being called via self.cls is cls global ? - Obj3ctiv3_C_88
@Obj3ctiv3_C_88, what do you mean by ”being called via self.cls is cls global“? - wpc062
@Obj3ctiv3_C_88 - if you find the source code (.../site-packages/google/protobuf/internal/python_message.py), it shows that MergeFrom is a function, defined within a function (def _AddMergeFromMethod(cls)) - dwanderson

1 Answers

6
votes

This may be able to help someone. I had the same error

TypeError: Parameter to MergeFrom() must be instance of same class: expected Hello_msg got Hello_msg.

when I imported the same class twice at two different paths, it results in two different classes imported at different paths (Even though they might have the same class name, Python sees them as two completely different class (check the ID of the class, you should find them to be different)).

To solve this issue, you need to make sure the same class (Hello_msg) is imported only once.