从类名反序列化python中的Protobuf

时间:2015-03-05 00:07:43

标签: python protocol-buffers

如何只知道protoc生成的类的字符串名称来反序列化协议缓冲区消息?

由于某种原因,我使用DESCRIPTOR.full_name获取的消息的完全限定名称与python类的实际位置不匹配,因此我无法使用以下函数对其进行反序列化:

def get_class( kls ):
    """Get class given a fully qualified name of a class"""
    parts = kls.split('.')
    module = ".".join(parts[:-1])
    m = __import__( module )
    for comp in parts[1:]:
        m = getattr(m, comp)
    return m

我只是得到ImportError没有模块(名字)。

任何帮助表示感谢。

P.S。:如果有帮助,我试图解决的更大问题是将protobuf消息序列化到数据库,然后将其反序列化(在这种情况下我使用postgresql和sqlalchemy)。由于常规的python pickle不起作用 - 我希望存储一个元组(message_cls_name, message_binary),其中message_cls_name是protobuf消息的完全限定名称,message_binary是调用的结果信息SerializeToString。我不清楚的部分是如何将消息输出并将其反序列化为适当的protobuf类。

1 个答案:

答案 0 :(得分:7)

这是一个示例解决方案..

from ocmg_common.protobuf.rpc_pb2 import Exception as PBException
from importlib import import_module

pb_message = PBException(message='hello world')
pb_message_string = pb_message.SerializeToString()

def deserialize(message, typ):
    module_, class_ = typ.rsplit('.', 1)
    class_ = getattr(import_module(module_), class_)
    rv = class_()
    rv.ParseFromString(message)
    return rv

print(deserialize(pb_message_string, 'ocmg_common.protobuf.rpc_pb2.Exception'))

将输出

(env)➜ httppost git:(master) ✗ python test.py
message: "hello world"

如果您不知道该模块,但只有DESCRIPTOR.full_name您必须以相同的方式命名它们,或者创建一个将完整描述符名称映射到模块的函数。否则你会被困住,不知道从哪里导入模块。

我希望它能帮到你..;)
祝你好运..