что также дает именно тот результат, который вы ожидаете

ел бы иметь возможность выгружать словарь, содержащий длинные строки, которые я хотел бы иметь в стиле блока для удобства чтения. Например:

foo: |
  this is a
  block literal
bar: >
  this is a
  folded block

PyYAML поддерживает загрузку документов с этим стилем, но я не могу найти способ выгрузить документы таким образом. Я что-то пропустил?

Ответы на вопрос(3)

Решение Вопроса
import yaml

class folded_unicode(unicode): pass
class literal_unicode(unicode): pass

def folded_unicode_representer(dumper, data):
    return dumper.represent_scalar(u'tag:yaml.org,2002:str', data, style='>')
def literal_unicode_representer(dumper, data):
    return dumper.represent_scalar(u'tag:yaml.org,2002:str', data, style='|')

yaml.add_representer(folded_unicode, folded_unicode_representer)
yaml.add_representer(literal_unicode, literal_unicode_representer)

data = {
    'literal':literal_unicode(
        u'by hjw              ___\n'
         '   __              /.-.\\\n'
         '  /  )_____________\\\\  Y\n'
         ' /_ /=== == === === =\\ _\\_\n'
         '( /)=== == === === == Y   \\\n'
         ' `-------------------(  o  )\n'
         '                      \\___/\n'),
    'folded': folded_unicode(
        u'It removes all ordinary curses from all equipped items. '
        'Heavy or permanent curses are unaffected.\n')}

print yaml.dump(data)

Результат:

folded: >
  It removes all ordinary curses from all equipped items. Heavy or permanent curses
  are unaffected.
literal: |
  by hjw              ___
     __              /.-.\
    /  )_____________\\  Y
   /_ /=== == === === =\ _\_
  ( /)=== == === === == Y   \
   `-------------------(  o  )
                        \___/

Для полноты, нужно также иметь str реализации, но я буду ленивым :-)

 Anthon23 авг. 2018 г., 09:43
Сложно было бы, конечно, заставить PyYAML контролировать васгде сложить сложенные скаляры. Без этого элемента управления вы можете использовать простые (многострочные) скаляры.
 Dave23 сент. 2016 г., 21:58
Благодарю. Извините за странный комментарий.
 Gary van der Merwe22 сент. 2016 г., 13:20
Это бумажный свиток, скопированный и вставленный из документации pyyaml.
 Dave21 сент. 2016 г., 20:29
На первый взгляд я подумал, что это пенис. Что я на самом деле смотрю здесь?

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

import sys
import ruamel.yaml

folded = ruamel.yaml.scalarstring.FoldedScalarString
literal = ruamel.yaml.scalarstring.LiteralScalarString

yaml = ruamel.yaml.YAML()

data = dict(
    foo=literal('this is a\nblock literal\n'), 
    bar=folded('this is a folded block\n'),
)

data['bar'].fold_pos = [data['bar'].index(' folded')]

yaml.dump(data, sys.stdout)

который дает:

foo: |
  this is a
  block literal
bar: >
  this is a
  folded block

fold_pos Атрибут ожидает обратимую итерацию,представляющие позиции пробелов указав, где сложить.

Если в ваших строках никогда не было символов канала ('|'), вы могли бы сделать что-то вроде:

import re

s = 'this is a|folded block\n'
sf = folded(s.replace('|', ' '))  # need to have a space!
sf.fold_pos = [x.start() for x in re.finditer('\|', s)]  # | is special in re, needs escaping


data = dict(
    foo=literal('this is a\nblock literal\n'), 
    bar=sf,  # need to have a space
)

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

что также дает именно тот результат, который вы ожидаете

pyyaml поддерживает сброс буквенных или сложенных блоков.

С помощьюRepresenter.add_representer

определяющие типы:

class folded_str(str): pass

class literal_str(str): pass

class folded_unicode(unicode): pass

class literal_unicode(str): pass

Затем вы можете определить представителей для этих типов. Обратите внимание, что в то время какGary«sрешение отлично работает для Unicode, вам может потребоваться дополнительная работа, чтобы заставить строки работать правильно (см.реализация представления_стр).

def change_style(style, representer):
    def new_representer(dumper, data):
        scalar = representer(dumper, data)
        scalar.style = style
        return scalar
    return new_representer

import yaml
from yaml.representer import SafeRepresenter

# represent_str does handle some corner cases, so use that
# instead of calling represent_scalar directly
represent_folded_str = change_style('>', SafeRepresenter.represent_str)
represent_literal_str = change_style('|', SafeRepresenter.represent_str)
represent_folded_unicode = change_style('>', SafeRepresenter.represent_unicode)
represent_literal_unicode = change_style('|', SafeRepresenter.represent_unicode)

Затем вы можете добавить эти представители в дампер по умолчанию:

yaml.add_representer(folded_str, represent_folded_str)
yaml.add_representer(literal_str, represent_literal_str)
yaml.add_representer(folded_unicode, represent_folded_unicode)
yaml.add_representer(literal_unicode, represent_literal_unicode)

... и проверить это:

data = {
    'foo': literal_str('this is a\nblock literal'),
    'bar': folded_unicode('this is a folded block'),
}

print yaml.dump(data)

результат:

bar: >-
  this is a folded block
foo: |-
  this is a
  block literal
С помощьюdefault_style

Если вы заинтересованы в том, чтобы все ваши строки соответствовали стилю по умолчанию, вы также можете использоватьdefault_style аргумент ключевого слова, например:

>>> data = { 'foo': 'line1\nline2\nline3' }
>>> print yaml.dump(data, default_style='|')
"foo": |-
  line1
  line2
  line3

или для сложенных литералов:

>>> print yaml.dump(data, default_style='>')
"foo": >-
  line1

  line2

  line3

или для двойных кавычек:

>>> print yaml.dump(data, default_style='"')
"foo": "line1\nline2\nline3"
Предостережения:

Вот пример того, чего вы можете не ожидать:

data = {
    'foo': literal_str('this is a\nblock literal'),
    'bar': folded_unicode('this is a folded block'),
    'non-printable': literal_unicode('this has a \t tab in it'),
    'leading': literal_unicode('   with leading white spaces'),
    'trailing': literal_unicode('with trailing white spaces  '),
}
print yaml.dump(data)

результаты в:

bar: >-
  this is a folded block
foo: |-
  this is a
  block literal
leading: |2-
     with leading white spaces
non-printable: "this has a \t tab in it"
trailing: "with trailing white spaces  "
1) непечатные символы

Смотрите спецификацию YAML для экранированных символов (Раздел 5.7):

Обратите внимание, что escape-последовательности интерпретируются только в скалярах с двойными кавычками. Во всех других скалярных стилях символ «\» не имеет специального значения, а непечатные символы недоступны.

Если вы хотите сохранить непечатные символы (например, TAB), вам нужно использовать скаляры в двойных кавычках. Если вы можете создать скаляр с буквальным стилем, и там есть непечатаемый символ (например, TAB), ваш дампер YAML не соответствует.

Например.pyyaml обнаруживает непечатный символ\t и использует стиль в двойных кавычках, даже если указан стиль по умолчанию:

>>> data = { 'foo': 'line1\nline2\n\tline3' }
>>> print yaml.dump(data, default_style='"')
"foo": "line1\nline2\n\tline3"

>>> print yaml.dump(data, default_style='>')
"foo": "line1\nline2\n\tline3"

>>> print yaml.dump(data, default_style='|')
"foo": "line1\nline2\n\tline3"
2) пробелы в начале и конце

Еще одна полезная информация в спецификации:

Все начальные и конечные пробельные символы исключены из содержимого

Это означает, что если ваша строка имеет пробел в начале или в конце, они не будут сохранены в скалярных стилях, кроме двойных кавычек. Как следствие,pyyaml пытается определить, что находится в вашем скаляре, и может вызвать двойные кавычки.

 paulkernstock02 янв. 2019 г., 17:29
На PyYAML 3.13 я сталкиваюсьyaml.representer.RepresenterError: cannot represent an object при попытке использовать это решение. Вот суть того, что я пытаюсь сделать:gist.github.com/paulkernstock/6df1c7ad37fd71b1da3cb05e70b9f522
 Anthon23 авг. 2018 г., 09:40
Вы получаете индикатор зачистки (приборная панель после| а также>) потому что у вас нет строк, оканчивающихся на новую строку, где в YAML ОП есть эти одинарные завершающие символы новой строки в обоих скалярах. Просто добавление новой строки должно решить эту проблему. Вы также не свернете сложенный скаляр там, где ОП ожидает, что он будет сложен, в результате чего все будет в одной строке (так как он достаточно широкий). Это несоответствие не так легко устранить в PyYAML.

Ваш ответ на вопрос