Какой самый элегантный способ внести изменения в элементы объекта protobuf в python? - PullRequest
1 голос
/ 03 апреля 2019

Вот файл конфигурации , который представляет объект protobuf:

model {
  faster_rcnn {
    num_classes: 37
    image_resizer {
      keep_aspect_ratio_resizer {
        min_dimension: 600
        max_dimension: 1024
      }
    }
    ...

Я хочу использовать python, чтобы прочитать это в объект, внести некоторые изменения в некоторые значения и затем записать его обратно в файл конфигурации.

Осложняющим фактором является то, что это довольно большой объект, построенный из множества файлов .proto.

Мне удалось выполнить задачу, преобразовав протобуф в словарь, внеся изменения, а затем преобразовав обратно в протобуф, например:

import tensorflow as tf
from google.protobuf.json_format import MessageToDict
from google.protobuf.json_format import ParseDict
from google.protobuf import text_format
from object_detection.protos import pipeline_pb2

def get_configs_from_pipeline_file(pipeline_config_path, config_override=None):

  '''
  read .config and convert it to proto_buffer_object
  '''

  pipeline_config = pipeline_pb2.TrainEvalPipelineConfig()
  with tf.gfile.GFile(pipeline_config_path, "r") as f:
    proto_str = f.read()
    text_format.Merge(proto_str, pipeline_config)
  if config_override:
    text_format.Merge(config_override, pipeline_config)
  return pipeline_config

configs = get_configs_from_pipeline_file('faster_rcnn_resnet101_pets.config')

d = MessageToDict(configs)
d['model']['fasterRcnn']['numClasses']=999

config2 = pipeline_pb2.TrainEvalPipelineConfig()
c = ParseDict(d, config2)

s = text_format.MessageToString(c)

with open('/path/test.config', 'w+') as fh:
    fh.write(str(s))

Я хотел бы иметь возможность вносить изменения в объект protobuf напрямую, без необходимости преобразования в словарь. Проблема, однако, заключается в том, что неясно, как «пройтись по дому», чтобы найти правильные ссылки на переменные, значения которых я хотел бы изменить. Это особенно верно, когда задействовано несколько файлов .proto.

Мне удалось выполнить редактирование примерно так, но я надеюсь, что есть лучший способ:

configs.model.ListFields()[0][1].num_classes = 99
...