Невозможно получить объекты PyYAML для правильного представления - PullRequest
0 голосов
/ 05 января 2019

Я использую PyYaml для регенерации файла YAML, но у меня есть нежелательные угловые скобки вокруг выводимых данных:

Исходный файл YAML:

 Outputs:
  HarvestApi:
    Description: URL for application
    Value: !Ref LocationRef
    Export:
      Name: HarvestApi

и файл python должен просто проанализировать и затем вывести YAML:

#!/usr/bin/env python3.6

import yaml
import sys

class RefTag(yaml.YAMLObject):
  yaml_tag = u'Ref'
  def __init__(self, text):
    self.text = text
  def __repr__(self):
    return "%s( text=%r)" % ( self.__class__.__name__, self.text)
  @classmethod
  def from_yaml(cls, loader, node):
    return RefTag(node.value)
  @classmethod
  def to_yaml(cls, dumper, data):
    return dumper.represent_scalar(cls.yaml_tag, data.text)
yaml.SafeLoader.add_constructor('!Ref', RefTag.from_yaml)
yaml.SafeDumper.add_multi_representer(RefTag, RefTag.to_yaml)

yaml_list = None
with open("./yaml-test.yml", "r")  as file:  
  try:
    yaml_list = yaml.safe_load(file)
  except yaml.YAMLError as exc:
    print ("--", exc)
    sys.exit(1)

print (yaml.dump(yaml_list, default_flow_style=False))

Но вместо этого выводит это:

Outputs:
  HarvestApi:
    Description: URL for application
    Export:
      Name: HarvestApi
    Value: !<Ref> 'LocationRef'

Эти дополнительные угловые скобки вокруг объекта Ref - это то, что мне нужно удалить.

1 Ответ

0 голосов
/ 05 января 2019

Основная проблема в том, что ваш тег не начинается с восклицательного знака отметка. Просто добавив, что даст вам ожидаемый результат. За ссылку см. пример PyYAML для Monster класс.

Дополнительные проблемные вещи:

  • В FAQ на yaml.org с сентября 2006 г. указано, что рекомендуемое расширение файла для YAML файлы .yaml

  • Вывод (и загрузка) PyYAML имеет потоковый интерфейс, но имеет сильно злоупотребляли удобством варианта пропустить поток, после чего вывод записывается в буфер памяти, который возвращается в виде строки. Используя это, чтобы затем вывести полученную строку, используя:

    print(dump(yaml_list, ...))
    

    медленный и неэффективная память.

  • Вы регистрируете свой погрузчик и самосвал для RefTag на SafeLoader, что хорошо, так как нет необходимости опасаться PyYAML Loader и Dumper по умолчанию. Но тогда вы звоните yaml.dump() вместо yaml.safe_dump(). Бывший работает, но использовать последний лучше, так как он будет жаловаться на незарегистрированных объекты в вашей структуре данных (если, конечно, с вводом, который вы сейчас используете).

Так что измените вещи на:

#!/usr/bin/env python3.6

import yaml
import sys

class RefTag(yaml.YAMLObject):
  yaml_tag = u'!Ref'
  def __init__(self, text):
    self.text = text
  def __repr__(self):
    return "%s( text=%r)" % ( self.__class__.__name__, self.text)
  @classmethod
  def from_yaml(cls, loader, node):
    return RefTag(node.value)
  @classmethod
  def to_yaml(cls, dumper, data):
    return dumper.represent_scalar(cls.yaml_tag, data.text)

yaml.SafeLoader.add_constructor('!Ref', RefTag.from_yaml)
yaml.SafeDumper.add_multi_representer(RefTag, RefTag.to_yaml)

yaml_list = None
with open("./yaml-test.yaml", "r")  as file:  
  try:
    yaml_list = yaml.safe_load(file)
  except yaml.YAMLError as exc:
    print ("--", exc)
    sys.exit(1)

yaml.safe_dump(yaml_list, sys.stdout, default_flow_style=False)

, что дает:

Outputs:
  HarvestApi:
    Description: URL for application
    Export:
      Name: HarvestApi
    Value: !Ref 'LocationRef'
...