2016-10-26 3 views
2

Google Протобуф меня смутил больше, чем когда-либо, и я пытаюсь понять, как все работает.Deserialize Google Protobuf двоичный файл

  1. Пожалуйста, помогите мне понять, правильно ли я это понимаю. .proto файл определяет определение сообщения и protoc является компилятором. Данные компилируются в двоичном файле (.pb). Верный? Если нет, можете ли вы, пожалуйста, помочь мне понять. Я не могу обрабатывать документы Google Protobuf. Это довольно запутанно. И не повезло с переполнением стека или другими блогами.

  2. Важно, я не могу изменить свой код на C++, где определена логика. С учетом сказанного я хотел бы deserialize filename.pb (двоичный файл) и проанализировать результаты через Python. Это возможно?

Спасибо за вашу помощь заранее!

ответ

3

Я не уверен, если я вообще отвечу на ваш вопрос, но я приведу вам пример. После того, как у вас есть протокол 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 или любой другой.

+0

Спасибо за подробное объяснение, но это действительно не решает мою проблему. У меня нет большого контроля над внешним сервером и я не могу изменить код для создания файла Protocol_pb2.py. Двоичный файл .pb, сгенерированный кодом C++, должен быть десериализован, чтобы я мог его проанализировать. –

+0

О, так что я понял, что ты совершенно неправ. У вас нет доступа к .proto-файлу? На самом деле, я не понимаю, чего вы хотите вообще: S Какова ваша цель? Вы хотите каким-то образом генерировать pb2.py из двоичного файла .pb? –

+0

Ну, ваш ответ помог мне двигаться вперед в правильном направлении. Скажем так, протоколы протобуфа не интуитивно понятны, и мне было трудно объяснить. У меня есть прото-файлы, но у меня пока нет файлов _pb2.py. Я просто понял, что мне нужно отправить свои прото-файлы на python и получить вывод в _pb2.py. Тогда я могу понять, как разбираться. В настоящее время у меня сложное приложение, поэтому мне нужно собрать все прото-файлы, которые скомпилируются в один вывод. –

-2

Да, вы можете использовать код python, сгенерированный protoc, чтобы де-сериализовать сообщение protobuf. Компилятор protoc выведет код на ваших целевых языках (в вашем случае python и C++).

Вот несколько ресурсов, которые могут помочь:

  1. Чтение и запись файлов в Python: https://docs.python.org/2/tutorial/inputoutput.html
  2. Python учебник для протокольных сообщений буфера: https://developers.google.com/protocol-buffers/docs/pythontutorial
+0

эта информация легко доступна, проинформируйте первые несколько ссылок для поисковой точки google тому, что вы опубликовали. Вопроситель хочет больше деталей. – Tanny

Смежные вопросы