Любые библиотеки yaml в Python, которые поддерживают демпинг длинных строк в виде блочных литералов или сложенных блоков?

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

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

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

2 Solutions collect form web for “Любые библиотеки yaml в Python, которые поддерживают демпинг длинных строк в виде блочных литералов или сложенных блоков?”

 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-реализации, но я буду ленив 🙂

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 отлично подходит для unicode, вам может понадобиться еще одна работа, чтобы заставить строки работать правильно (см. Реализацию представления_str ).

 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 и использует стиль с двойным pyyaml даже если указан стиль по умолчанию:

 >>> 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 пытается обнаружить то, что находится в вашем pyyaml и может заставить стиль с двойным pyyaml .

  • Загрузка документа в качестве исходной строки в yaml с помощью PyYAML
  • Создайте модель из YAML / JSON на лету
  • Установите pyyaml ​​с помощью pip / Add PyYaml в качестве зависимости от pip
  • Указание стилей для частей дампа PyYAML (II): последовательности
  • Преобразование CSV в YAML, с Unicode?
  • Разберите YAML и предположим, что определенный путь всегда является строкой
  • Может ли PyYAML сбрасывать элементы в не алфавитном порядке?
  • Есть ли способ построить объект, используя PyYAML construct_mapping после того, как все узлы завершат загрузку?
  • Python - лучший язык программирования в мире.