Разбор Google Fonts METADATA.pb — google.protobuf.message.DecodeError: Ошибка анализа сообщения

Я пытаюсь разобрать файл METADATA.pb из официального репозитория Google Fonts, который можно найти здесь: https://github.com/google/fonts (пример файла METADATA.pb для шрифта Roboto: https://github.com/google/fonts/blob/master/apache/roboto/METADATA.pb)

Для анализа файлов proto-buf требуется правильный формат. Его можно скачать как "public_fonts.proto" здесь: https://github.com/googlefonts/gftools/blob/master/Lib/gftools/fonts_public.proto

Я использовал его для создания файла кода Python с именем «fonts_public_pb2.py» с помощью этой команды:

protoc -I=. --python_out=. fonts_public.proto

И вот мой код, который импортирует этот сгенерированный файл, считывает содержимое файла METADATA.pb (неважно, какого именно, все они имеют одинаковую структуру), а затем пытается разобрать строку proto-buf.

#! /usr/bin/env python

import fonts_public_pb2

protobuf_file_path = 'METADATA.pb'
protobuf_file = open(protobuf_file_path, 'rb')
protobuf = protobuf_file.read()

font_family = fonts_public_pb2.FamilyProto()
font_family.ParseFromString(protobuf)

Всего несколько строк, ничего сложного, но вывод всегда один и тот же:

Traceback (most recent call last):
  File "parse.py", line 22, in <module>
    font_family.ParseFromString(protobuf)
google.protobuf.message.DecodeError: Error parsing message

Обычно я не пишу код на Python, поэтому проблема здесь вполне может быть во мне, но, попробовав несколько разных вещей, я больше не знаю, что делать:

  • Использован уже созданный файл "fonts_public_pb2.py" из репозитория gftools: https://github.com/googlefonts/gftools/blob/master/Lib/gftools/fonts_public_pb2.py. Мои сгенерированные выходные данные из файла "public_fonts.proto" и этого файла почти идентичны, я проверяю Слияние. Ошибка осталась та же
  • Установите для всех «обязательных» полей в файле .proto значение «необязательно», снова сгенерируйте файл «fonts_public_pb2.py» — та же ошибка
  • Пробовал Python 2 и 3 - та же ошибка

person krebas    schedule 08.12.2019    source источник


Ответы (1)


Эти файлы METADATA.pb не являются двоичными файлами protobuf, они используют текстовый формат.

import fonts_public_pb2
from google.protobuf import text_format

protobuf_file_path = 'METADATA.pb'
protobuf_file = open(protobuf_file_path, 'r')
protobuf = protobuf_file.read()

font_family = fonts_public_pb2.FamilyProto()
text_format.Merge(protobuf, font_family)
print(font_family)
person Jan-Gerd    schedule 08.12.2019
comment
Хорошо, во-первых: Большое спасибо, или, потому что мы оба немцы: Danke dir :) Во-вторых: Я бы сам не догадался, я просто предположил, что ParseFromString требует... строки!?! В-третьих: не могли бы вы убрать в своем ответе букву «b» из «rb»? Здесь нужна настоящая строка, иначе выдает эту ошибку: TypeError: a bytes-like object is required, not 'str' Спасибо :) - person krebas; 10.12.2019
comment
Добро пожаловать и gern geschehen. ParseFromString нужна строка... байтов! Определенно не самое очевидное имя метода в истории имен методов. Я исправил код, хотя на моей машине это не имеет никакого значения (Python 3 в macOS). - person Jan-Gerd; 11.12.2019