Хотя слова «правильный YAML» не совсем точны, и их лучше сформулировать как
«Вывод YAML выглядит так, как вы хотите, за исключением информации тега», к счастью, это дает
информация о том, как вы хотите, чтобы ваш YAML выглядел, поскольку существует бесконечное количество способов создания дампов объектов.
Если вы сбрасываете объект, используя ruamel.yaml
:
import sys
import ruamel.yaml
class MyObject:
def __init__(self, a, b):
self.a = a
self.b = b
self.c = [a, b]
data = dict(x=MyObject(42, -1))
yaml = ruamel.yaml.YAML(typ='unsafe')
yaml.dump(data, sys.stdout)
это дает:
x: !!python/object:__main__.MyObject
a: 42
b: -1
c: [42, -1]
У вас есть тег !!python/object:__main__.MyObject
(ваш может отличаться в зависимости от того, где
класс определен и т. д.), и каждый из атрибутов класса выводится как ключи отображения.
Существует несколько способов избавиться от тега в этом дампе:
Регистрация классов
Добавьте classmethod
с именем to_yaml()
к каждому из ваших классов и
зарегистрировать эти классы. Вы должны сделать это для каждого из ваших классов,
но это позволяет вам использовать безопасный самосвал. Пример того, как
сделать это можно найти в
Документация
Post-процесс
Довольно просто постобработать вывод и удалить теги, которые для объектов всегда встречаются в строке
до отображения, и вы можете удалить от !!python
до конца строки
def strip_python_tags(s):
result = []
for line in s.splitlines():
idx = line.find("!!python/")
if idx > -1:
line = line[:idx]
result.append(line)
return '\n'.join(result)
yaml.encoding = None
yaml.dump(data, sys.stdout, transform=strip_python_tags)
и это дает:
x:
a: 42
b: -1
c: [42, -1]
Так как ахоры сбрасываются перед тегом, это "удаление с !!python
до конца строки ", также работает при сбросе объекта,
несколько ссылок.
Поменять самосвал
Вы также можете изменить подпрограмму небезопасного дампера для сопоставлений на
распознать тег, используемый для объектов, и изменить тег на «обычный»
один для dict / mapping (для которого обычно тег не выводится)
yaml.representer.org_represent_mapping = yaml.representer.represent_mapping
def my_represent_mapping(tag, mapping, flow_style=None):
if tag.startswith("tag:yaml.org,2002:python/object"):
tag = u'tag:yaml.org,2002:map'
return yaml.representer.org_represent_mapping(tag, mapping, flow_style=flow_style)
yaml.representer.represent_mapping = my_represent_mapping
yaml.dump(data, sys.stdout)
и это дает еще раз:
x:
a: 42
b: -1
c: [42, -1]
Эти два последних метода работают для всех экземпляров всех классов Python, которые вы определяете, без дополнительной работы.