Как импортировать модуль protobuf - PullRequest
0 голосов
/ 25 марта 2019

С файлом message.proto сохраняется в папке proto:

enter image description here

Я изменяю текущий рабочий каталог на папку proto:

cd /test/proto

Затем я запускаю grpc_tools.protoc, чтобы сгенерировать модуль Python protobuf:

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

message_pb2.py успешно сгенерирован:

enter image description here

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 Ответ

1 голос
/ 25 марта 2019

Я не думаю, что вы используете Protobuf правильно. Нет смысла выбирать Protobuf, поскольку весь смысл Protos в том, что они сериализуемы. Вместо этого вы должны использовать SerializeToString и ParseFromString, как указано в документации Protobuf здесь .

Как они там отмечают, вы не сможете на самом деле прочитать эти строки, потому что они на самом деле просто последовательность байтов, которая использует str для удобства.

РЕДАКТИРОВАТЬ: Глядя на это больше, Protobufs не маринованные, смотрите здесь для более подробной информации: https://groups.google.com/forum/#!topic/protobuf/VqWJ3BmQXVg

...