Формат дампа PyYAML

Я знаю, что есть несколько вопросов об этом на SO, но я не мог найти то, что искал.

Я использую pyyaml для чтения ( .load() ) файла .yml , изменения или добавления ключа, а затем пишу его ( .dump() ) еще раз. Проблема в том, что я хочу сохранить формат файла post-dump, но он изменяется.

Например, я редактирую ключ en.test.index.few чтобы сказать "Bye" вместо "Hello"

Python:

 with open(path, 'r', encoding = "utf-8") as yaml_file: self.dict = pyyaml.load(yaml_file) 

Затем, изменив ключ:

 with open(path, 'w', encoding = "utf-8") as yaml_file: dump = pyyaml.dump(self.dict, default_flow_style = False, allow_unicode = True, encoding = None) yaml_file.write( dump ) 

YAML:

До:

 en: test: new: "Bye" index: few: "Hello" anothertest: "Something" 

После:

 en: anothertest: Something test: index: few: Hello new: Bye 

Есть ли способ сохранить тот же формат ?, например, qoutes и order. Использую ли я для этого неправильный инструмент?

Я знаю, возможно, исходный файл не совсем корректен, но я не контролирую его (это файл Ruby on Rails i18n).

Большое спасибо.

3 Solutions collect form web for “Формат дампа PyYAML”

ruamel.yaml этого используйте ruamel.yaml .

Библиотека битвы! Сказка о двух библиотеках

PyYAML эффективно мертв и уже несколько лет. Что касается сложных вопросов, официальный сайт проекта на http://pyyaml.org, похоже, недавно был снят. На этом сайте размещен трекер, документация и загрузки PyYAML. На момент написания статьи все исчезло. Это не что иное, как бедствие. Добро пожаловать в другой день в open-source.

ruamel.yaml активно поддерживается . В отличие от PyYAML, ruamel.yaml поддерживает:

  • YAML <= 1.2. PyYAML поддерживает только YAML <= 1.1. Это очень важно, поскольку YAML 1.2 намеренно нарушает обратную совместимость с YAML 1.1 в нескольких случаях. Обычно это плохо. В этом случае это делает YAML 1.2 строгим надмножеством JSON. Поскольку YAML 1.1 не является строгим надмножеством JSON, это хорошо.
  • Круглосуточная охрана. При вызове yaml.dump() для дампа словаря, загруженного предыдущим вызовом yaml.load() :
    • PyYAML наивно игнорирует все форматирование ввода – включая комментарии, заказы, цитаты и пробелы. Отброшено, как много цифровых отходов в ближайшее доступное ведро бит.
    • ruamel.yaml умело уважает все форматирование ввода. Все. Вся стилистическая энчилада. Весь литературный шебанг. Все.

Миграция библиотек: следы кодовых слез

Поскольку ruamel.yaml является вилкой PyYAML и, следовательно, соответствует API PyYAML, переключение с PyYAML на ruamel.yaml в существующих приложениях обычно так же просто, как и замена всех экземпляров этого:

 # This imports PyYAML. Stop doing this. import yaml 

…с этим:

 # This imports "ruamel.yaml". Always do this. from ruamel import yaml 

Вот и все.

Никаких других изменений не требуется. Функции yaml.load() и yaml.dump() должны продолжать вести себя так, как ожидалось, – с дополнительными преимуществами теперь поддерживая YAML 1.2 и активно получая исправления ошибок.

Сохранение заграничных кругов и что он может сделать для вас

Для обратной совместимости с PyYaml функции yaml.load() и yaml.dump() по умолчанию не поддерживают сохранение в yaml.load() . Для этого явно передайте:

  • Необязательный параметр ключевого слова Loader=ruamel.yaml.RoundTripLoader для yaml.load() .
  • Необязательный параметр ключевого слова Dumper=ruamel.yaml.RoundTripDumper для yaml.dump() .

Пример любезно «заимствован» из документации ruamel.yaml :

 import ruamel.yaml inp = """\ # example name: # Yet another Great Duke of Hell. He's not so bad, really. family: TheMighty given: Ashtaroth """ code = ruamel.yaml.load(inp, Loader=ruamel.yaml.RoundTripLoader) code['name']['given'] = 'Astarte' # Oh no you didn't. print(ruamel.yaml.dump(code, Dumper=ruamel.yaml.RoundTripDumper), end='') 

Сделано. Комментарии, заказы, цитаты и пробелы теперь будут сохранены без изменений.

ТЛ; др

Всегда используйте ruamel.yaml . Никогда не используйте PyYAML. ruamel.yaml живет. PyYAML – это зловонный труп, гниющий на измельченном грунте PyPi.

Да здравствует ruamel.yaml .

Первый

Для представления данных словаря используется следующий код:

 mapping = list(mapping.items()) try: mapping = sorted(mapping) except TypeError: pass 

Именно поэтому заказ меняется

второй

Информация о том, как был представлен тип скаляра (с двойной кавычкой или нет), теряется при чтении (это основной подход библиотеки)

Резюме

Вы можете создать собственный класс на основе «Dumper» и перегрузить метод «Represent_mapping» для изменения поведения, как будет отображаться словарь

Для сохранения информации о двойных кавычках для скаляра вы также должны создать собственный класс на основе «Loader», но я боюсь, что это повлияет и на другие классы, и это будет сложно

В моем случае я хочу, " если значение содержит { или a } , в противном случае ничего. Например:

  en: key1: value is 1 key2: 'value is {1}' 

Чтобы выполнить это, скопируйте функцию Represent_str represent_str() из файла representer.py в модуль PyYaml и используйте другой стиль, если строка содержит { или a } :

 def represent_str(self, data): tag = None style = None # Add these two lines: if '{' in data or '}' in data: style = '"' try: data = unicode(data, 'ascii') tag = u'tag:yaml.org,2002:str' except UnicodeDecodeError: try: data = unicode(data, 'utf-8') tag = u'tag:yaml.org,2002:str' except UnicodeDecodeError: data = data.encode('base64') tag = u'tag:yaml.org,2002:binary' style = '|' return self.represent_scalar(tag, data, style=style) 

Чтобы использовать его в своем коде:

 import yaml def represent_str(self, data): ... yaml.add_representer(str, represent_str) 

В этом случае нет различий между клавишами и значениями, и этого достаточно для меня. Если вам нужен другой стиль для клавиш и значений, выполните одно и то же с функцией represent_mapping

  • Сохранить SQL в YAML как есть
  • ConfigObj / ConfigParser против использования файла настроек YAML для Python
  • Python и PYAML - yaml.scanner.ScannerError: значения отображения здесь не допускаются
  • Как я могу получить комментарии из файла YAML, используя ruamel.yaml в Python?
  • Разбор XML или YML в OpenCV с помощью Python
  • Вложенные переменные jinja2
  • Сохранить / выгрузить файл YAML с комментариями в PyYAML
  • pyyaml: демпинг без тегов
  • Python - лучший язык программирования в мире.