#python #yaml #dump #pyyaml #ruamel.yaml
#python #yaml #дамп #pyyaml #ruamel.yaml
Вопрос:
У меня был какой-то объект, который я хочу превратить в yaml, единственное, что мне нужно, чтобы иметь возможность поместить в него «!что угодно» без кавычек.
Когда я пробую это с pyyaml, я получаю ‘!anything’ внутри моего файла yaml.
Я уже пробовал использовать ruamel.yaml сохранил scalarstring и LiteralScalarString. И это вроде как работает, но не так, как мне нужно работать. Дело в том, что в итоге я получаю yaml, который выглядит следующим образом:
10.1.1.16:
text: '1470814.27'
confidence: |-
!anything
Но мне не нужен этот |-
символ.
Моя цель — получить yaml таким образом:
10.1.1.16:
text: '1470814.27'
confidence: !anything
Есть идеи, как я могу этого добиться?
Комментарии:
1. В YAML
!anything
(и, как правило, все, что начинается с!
) является тегом (т. Е. Не содержимым). Если вы хотите,!anything
чтобы он обрабатывался как содержимое, вы должны использовать одинарные или двойные кавычки или скаляр блока (|-
или>-
).2. @flyx итак, что мне делать, если я хочу иметь возможность дамп тега? Дело в том, что мне нужно каким-то образом иметь возможность записать его из моего кода на Python
Ответ №1:
Чтобы дамп пользовательского тега, вам необходимо определить тип и зарегистрировать представитель для этого типа. Вот как это сделать для скаляров:
import yaml
class MyTag:
def __init__(self, content):
self.content = content
def __repr__(self):
return self.content
def __str__(self):
return self.content
def mytag_dumper(dumper, data):
return dumper.represent_scalar("!anything", data.content)
yaml.add_representer(MyTag, mytag_dumper)
print(yaml.dump({"10.1.1.16": {
"text": "1470814.27",
"confidence": MyTag("")}}))
Это выдает
10.1.1.16:
confidence: !anything ''
text: '1470814.27'
Обратите внимание на ''
за тегом, который является помеченным скаляром (нет, вы не можете избавиться от него). Вы также можете помечать коллекции тегами, но вам нужно будет использовать represent_sequence
или represent_mapping
соответственно.
Комментарии:
1. Первая потоковая передача в буфер StringIO, а затем печать содержимого этого буфера излишне неэффективна (как с точки зрения потребления памяти, так и по времени) по сравнению с прямой потоковой передачей в
sys.stdout
. Поэтому вы всегда должны использоватьyaml.dump(data, sys.stdout)
вместоprint(yaml.dump(data))
.
Ответ №2:
Вопреки комментарию @flix, в YAML вам не нужно заключать тег в одинарные или двойные кавычки (или скалярный блок). Вы можете попробовать анализатор ссылок Орена Бен-Кики (программно полученный из спецификации YAML), чтобы подтвердить, что ваш ожидаемый результат является действительным YAML.
Пустое содержимое обычно загружается как None
в Python (как устаревшим PyYAML, так и ruamel.yaml). Помеченное пустое содержимое, конечно, может указывать только на существование определенного экземпляра без указания какого-либо значения.
ruamel.yaml вполне может выполнить ожидаемый результат в обратном направлении:
import sys
from ruamel.yaml import YAML
yaml_str = """
10.1.1.16:
text: '1470814.27'
confidence: !anything
"""
yaml = YAML()
data = yaml.load(yaml_str)
yaml.dump(data, sys.stdout)
дает:
10.1.1.16:
text: '1470814.27'
confidence: !anything
Вы можете сгенерировать объект, который сбрасывает только тег без значения с нуля (как это делает анализатор), но если вы не хотите вдаваться в подробности, вы можете просто загрузить помеченный объект и добавить его в свою структуру данных:
import sys
import ruamel.yaml
yaml = ruamel.yaml.YAML()
def tagged_empty_scalar(tag):
return yaml.load('!' tag)
data = {'10.1.1.16': dict(text='1470814.27', confidence=tagged_empty_scalar('anything'))}
yaml.dump(data, sys.stdout)
Вы можете получить точно такой же результат в PyYAML и без кавычек, но это сложнее.