如何导入protobuf模块

时间:2019-03-25 18:31:39

标签: python protocol-buffers proto

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

java docs

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

cd /test/proto

然后我正在运行grpc_tools.protoc来生成protobuf Python模块:

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

message_pb2.py成功生成:

java docs

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时发生的另一个问题。当我尝试使用PicklingError方法将message放入多处理queue时,会发生相同的put

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放在同一文件夹中,则不会发生此问题:

enter image description here

修改后的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

1 个答案:

答案 0 :(得分:1)

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

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

编辑:仔细研究一下,Protobufs不能腌制,请参见此处了解更多详细信息:https://groups.google.com/forum/#!topic/protobuf/VqWJ3BmQXVg