Как использовать ruamel.yaml для вывода литеральных скаляров

Я искал и нашел «похожие» сообщения, но ничего, что прямо отвечало бы на мой вопрос. Я также нашел здесь сообщение stackoverflow, но ответов нет.

Мне нужно записать в файл yaml в следующем формате:

any_value: 123.4
data_points: |-
  0.0, 1.0
  0.1, 1.5
  0.2, 1.7

Если я использую длинную строку, содержащую \n, она просто напечатает ее как есть:

any_value: 123.4
data_points: "0.0, 1.0\n0.1, 1.5\n0.2, 1.7"

Это не то, чего я хочу. Я также могу передать его как список, где каждый элемент выглядит так

['0.0, 1.0', '0.1, 1.5', '0.2, 1.7']

Но это приводит только к

any_value: 123.4
data_points:
- 0.0, 1.0
- 0.1, 1.5
- 0.2, 1.7

Похоже на первую, но не она. Как мне заставить ruamel.yaml сбрасывать его так, как я хочу?


person Ivar Stange    schedule 14.06.2018    source источник
comment
Этот другой вопрос касается сложенных скаляров, у вас есть буквальный скаляр в стиле блока. Свернутые скаляры в настоящее время не передаются туда и обратно, как свернутые скаляры, отчасти потому, что сложнее хранить информацию о том, где сворачиваться, а также потому, что свернутые скаляры используются гораздо реже (и полезны).   -  person Anthon    schedule 14.06.2018


Ответы (1)


Вам нужны не свернутые скаляры (которые будут иметь > вместо |), а литерал блочного стиля скаляры.

Общий способ решить эту проблему - посмотреть, может ли ruamel.yaml выполнить обратную передачу того, что вы хотите:

import sys
import ruamel.yaml

yaml_str = """\
any_value: 123.4
data_points: |-
  a
  b
"""

yaml = ruamel.yaml.YAML()
data = yaml.load(yaml_str)
yaml.dump(data, sys.stdout)

это дает:

any_value: 123.4
data_points: |-
  a
  b

Поскольку вывод выглядит так же, как ввод, проверьте тип, который ruamel.yaml использует для сохранения литеральной информации о стиле:

print(type(data['data_points']))

который показывает, что ruamel.yaml использует внутри:

<class 'ruamel.yaml.scalarstring.LiteralScalarString'>

Обладая этими знаниями, вы можете:

from ruamel.yaml.scalarstring import LiteralScalarString

data['data_points'] = literalScalarString("""\
0.0, 1.0
0.1, 1.5
0.2, 1.7""")

yaml.dump(data, sys.stdout)

в результате чего:

any_value: 123.4
data_points: |-
  0.0, 1.0
  0.1, 1.5
  0.2, 1.7

Обратите внимание, что тире в |- указывает на то, что ваш скаляр не имеет конечной новой строки. Вот почему ваша многострочная строка Python также не должна иметь ее.

Также есть функция walk_tree() в ruamel/yaml/scalarstring.py, которая может помочь, это:

проходит по простому дереву yaml (рекурсивно в значениях dict и элементах списка) и преобразует строки, которые имеют несколько строк, в буквальные скаляры

person Anthon    schedule 14.06.2018
comment
Если это решит вашу проблему, рассмотрите возможность пометить этот ответ как принятый (щелкнув v слева рядом с верхней частью ответа. Тогда другие узнают, что это сработало для вас, не читая комментарии. - person Anthon; 15.06.2018
comment
Теперь следует использовать LiteralScalarString вместо PreservedScalarString - person jmb; 02.03.2020