Я не уверен, если я вообще отвечу на ваш вопрос, но я приведу вам пример. После того, как у вас есть протокол Protocol_pb2.py, вы можете легко разобрать сообщения с помощью API protobuf python (и, возможно, struct
). Я не специалист в protobuf, но я по крайней мере разобрал сообщения Mumble. Теперь, я не знаю, как именно вы используете protobuf и зачем, но этот пример показывает, как разбирать сообщения mumble (которые используют protobuf), и, надеюсь, даст вам некоторое представление. Итак:
Импорт protoc созданный Protobuf-файл (создать его в том, что я ответил на ваш последний вопрос) & структура:
import struct
import Mumble_pb2 as mumble_protobuf
Модуль mumble_protobuf будет содержать различные сообщения, определенные в вашем .proto, преобразованный в формат Python. Вы можете сохранить различные типы сообщений, чтобы, например, в Словаре:
PACKET_TYPES = {
0: mumble_protobuf.Version,
1: mumble_protobuf.UDPTunnel,
2: mumble_protobuf.Authenticate,
...
я пропущу вещи здесь, но как только вы получите двоичные данные пакета вы можете разобрать его. Я полагаю, что каждое приложение делает все по-другому, но, например, mumble отправляет сообщение protobuf с префиксом 2 байта, которые включают тип сообщения, и 4 байта, которые указывают длину пакета. Это, вероятно, сделано по-другому в вашем приложении. В любом случае, вы должны каким-то образом знать, какое сообщение вы будете анализировать (при условии, что ваш протокол имеет несколько типов сообщений).Но в качестве примера:
# The header format corresponds to the mumble packet that send the prefix + protobuf-msg
HEADER_FORMAT = ">HI" # Big endian, unsigned short + unsigned int
packet_type, packet_length = struct.unpack_from(HEADER_FORMAT, buffer)
Если у вас есть несколько сообщений в буфере вам нужно будет извлечь пакетные данные из буфера на основе длины пакета. Когда вы знаете тип сообщения, вы можете его разобрать. Эта часть просто выберет класс, соответствующий типу сообщения из файла pb2, и проанализирует сообщение на его основе.
MessageClass = PACKET_TYPES[packet_type]
message = MessageClass()
message.ParseFromString(packet_data)
Теперь message
наконец содержит разобранное Protobuf сообщение, и вы можете использовать его, как вы бы при создании одного: вы можете ссылаться на поля и т.д.: message.UserName
или любой другой.
Спасибо за подробное объяснение, но это действительно не решает мою проблему. У меня нет большого контроля над внешним сервером и я не могу изменить код для создания файла Protocol_pb2.py. Двоичный файл .pb, сгенерированный кодом C++, должен быть десериализован, чтобы я мог его проанализировать. –
О, так что я понял, что ты совершенно неправ. У вас нет доступа к .proto-файлу? На самом деле, я не понимаю, чего вы хотите вообще: S Какова ваша цель? Вы хотите каким-то образом генерировать pb2.py из двоичного файла .pb? –
Ну, ваш ответ помог мне двигаться вперед в правильном направлении. Скажем так, протоколы протобуфа не интуитивно понятны, и мне было трудно объяснить. У меня есть прото-файлы, но у меня пока нет файлов _pb2.py. Я просто понял, что мне нужно отправить свои прото-файлы на python и получить вывод в _pb2.py. Тогда я могу понять, как разбираться. В настоящее время у меня сложное приложение, поэтому мне нужно собрать все прото-файлы, которые скомпилируются в один вывод. –