如何导入protobuf模块

How to import protobuf module

message.proto 文件保存在 proto 文件夹中:

我将当前工作目录更改为 proto 文件夹:

cd /test/proto

然后我运行宁grpc_tools.protoc生成protobuf Python模块:

python -m grpc_tools.protoc -I. --python_out=.  message.proto

message_pb2.py生成成功:

script.py 位于上面的一个文件夹中,它包含:

from proto import message_pb2

message = message_pb2.Message(field_a = 'Monday')
print type(message) 

当 运行 script.py 成功加载 message_pb2 模块并声明 Message 实例时:

<class 'message_pb2.Message'>

现在我想腌制消息对象,将两行附加到 script.py:

import pickle
pickled = pickle.dumps(message)

这会引发 pickle.PicklingError 异常:

pickle.PicklingError: Can't pickle <class 'message_pb2.Message'>: it's not found as message_pb2.Message

稍后编辑

我在这里使用pickle模块的原因是为了描述使用multiprocessing.queue时发生的另一个问题。当我尝试使用 put 方法将 message 放入多处理 queue 时,会发生相同的 PicklingError

from multiprocessing import Queue
queue = Queue()
queue.put(message)

它导致同样的错误:

PicklingError: Can't pickle <class 'message_pb2.Message'>: import of module message_pb2 failed

如何解决这个问题?

有趣的是,如果我将生成的 message_pb2 Python 模块与 script.py 放在同一个文件夹中,问题就不会发生:

已修改 script.py

import message_pb2

message = message_pb2.Message(field_a = 'Monday')
from multiprocessing import Queue
queue = Queue()
queue.put(message)

解决方案:

使用SerializeToString方法:

queue.put(message.SerializeToString())
msg = queue.get()
print msg.field_a

我认为您没有正确使用 Protobuf。腌制 Protobuf 没有意义,因为 Protos 的全部意义在于它们是可序列化的。相反,您应该使用 SerializeToStringParseFromString,如 Protobuf docs here.

中所述

正如他们在那里指出的那样,您将无法真正读取这些字符串,因为它们实际上只是为了方便而使用 str 的字节序列。

编辑:进一步研究,Protobufs 不可 pickle,详情请见此处:https://groups.google.com/forum/#!topic/protobuf/VqWJ3BmQXVg