Преобразовать многострочные значения YAML в сложный скалярный стиль?

Используя ruamel.yaml, я попытался получить YAML в определенном стиле, более конкретно, где однострочные строки начинаются с той же строки, что и многострочные строки с использованием сложенного скалярного стиля ( | / |- ) и строк, ограниченных определенное количество символов (обернутое словами).

Моя попытка в настоящее время сильно зависит от аналогичной функции, называемой walk_tree в источниках :

 #!/usr/bin/env python import ruamel.yaml from ruamel.yaml.scalarstring import ScalarString, PreservedScalarString def walk_tree(base): from ruamel.yaml.compat import string_types if isinstance(base, dict): for k in base: v = base[k] if isinstance(v, string_types): v = v.replace('\r\n', '\n').replace('\r', '\n').strip() base[k] = ScalarString(v) if '\n' in v else v else: walk_tree(v) elif isinstance(base, list): for idx, elem in enumerate(base): if isinstance(elem, string_types) and '\n' in elem: print(elem) # @Anthon: this print is in the original code as well base[idx] = preserve_literal(elem) else: walk_tree(elem) with open("input.yaml", "r") as fi: inp = fi.read() loader=ruamel.yaml.RoundTripLoader data = ruamel.yaml.load(inp, loader) walk_tree(data) dumper = ruamel.yaml.RoundTripDumper with open("output.yaml", "w") as fo: ruamel.yaml.dump(data, fo, Dumper=dumper, allow_unicode=True) 

Но затем я получаю исключение: ruamel.yaml.representer.RepresenterError: cannot represent an object: … Я не получаю исключения, если заменить ScalarString на PreservedScalarString как это имеет место в исходном коде walk_tree но затем я снова получаю литералы, что не то, что я хочу.

Итак, как мой код может быть исправлен, чтобы он работал?

    Класс ScalarString является базовым классом для PreservedScalarString , у него нет представителя, как вы узнали. Вы должны просто сделать / сохранить эту строку Python, так как это относится к специальным символам соответствующим образом (цитируя строки, которые должны быть указаны в соответствии со спецификацией YAML).

    Предполагая, что у вас есть такой ввод:

     - 1 - abc: | this is a short string scalar with a newline in it - "there are also a multiline\nsequence element\nin this file\nand it is longer" 

    Вероятно, вы хотите сделать что-то вроде:

     import ruamel.yaml from ruamel.yaml.scalarstring import PreservedScalarString, preserve_literal def walk_tree(base): from ruamel.yaml.compat import string_types def test_wrap(v): v = v.replace('\r\n', '\n').replace('\r', '\n').strip() return v if len(v) < 72 else preserve_literal(v) if isinstance(base, dict): for k in base: v = base[k] if isinstance(v, string_types) and '\n' in v: base[k] = test_wrap(v) else: walk_tree(v) elif isinstance(base, list): for idx, elem in enumerate(base): if isinstance(elem, string_types) and '\n' in elem: base[idx] = test_wrap(elem) else: walk_tree(elem) with open("input.yaml", "r") as fi: data = ruamel.yaml.round_trip_load(fi) walk_tree(data) with open("output.yaml", "w") as fo: ruamel.yaml.round_trip_dump(data, fo) 

    получить выход:

     - 1 - abc: "this is a short string scalar with a newline\nin it" - |- there are also a multiline sequence element in this file and it is longer 

    Некоторые примечания:

    • у вас, вероятно, не было элементов последовательности, в которых строки, поскольку вы не импортировали файл preserve_literal , хотя он все еще использовался в скопированном коде.
    • Я укомплектовал «обертывающий» код в test_wrap, используемый как значением, так и переносом элементов, максимальная длина строки для этого была установлена ​​в 72 символа.
    • data[1]['abc'] значения data[1]['abc'] загружаются как PreservedScalarString . Если вы хотите сохранить существующие строковые строковые строковые скаляры, вы должны проверить их перед тестированием типа string_types .
    • Я использовал сокращенные функции round_trip_load() и round_trip_dump() (последнее позволяет allow_unicode=True автоматически).
    • Возможно, вам придется установить параметр width для round_trip_dump() примерно на 1000, чтобы предотвратить автоматическое обертывание строк, если вы увеличиваете 72 в примере до значения по умолчанию 80.