Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

isinstance doesn't work when use reflection of python protobuf v2.6.1

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?

like image 941
wpc062 Avatar asked Aug 05 '15 21:08

wpc062


People also ask

Does Protobuf use reflection?

reflection. Contains a metaclass and helper functions used to create protocol message classes from Descriptor objects at runtime.

Is Protobuf human readable?

If you're using the protobuf package, the print function/statement will give you a human-readable representation of the message, because of the __str__ method :-).

What is the Protobuf wire format?

Protocol Buffers is a high-performance, compact binary wire format invented by Google who use it internally so they can communicate with their internal network services at very high speed.


1 Answers

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.

like image 122
Tony Kuo Avatar answered Nov 15 '22 08:11

Tony Kuo