Возможно ли сохранить структуру блока YAML при сбрасывании анализируемого документа?

Мы используем PyYAML для готовых конфигурационных файлов для разных сред. Но наши блоки YAML теряют целостность.

input.yml

 pubkey: | -----BEGIN PUBLIC KEY----- MIGfMA0GCSq7OPxRrQEBAQUAA4GNADCBiQKBgQCvRVUKp6pr4qBEnE9lviuyfiNq QtG/OCyBDXL4Bh3FmUzfNI+Z4Bh3FmUx+z2n0FCv/4BpgHTDl8D95NPopWVo1RH2 UfhyMd6dQ/x9T5m+y38JMzmSVAk+Fqu8ya18+yQVOEyEIx3Gxpsgegow33gcxfjK EsUgJHXcpw7OPxRrCQIDAQAB -----END PUBLIC KEY----- 

… выполнение этой программы с помощью python3 …

 import yaml with open('input.yml', mode='r') as f: parsed = yaml.safe_load(f) with open('output.yml', mode='w') as f: yaml.dump(parsed, f) 

… производит этот output.yml

 pubkey: '-----BEGIN PUBLIC KEY----- MIGfMA0GCSq7OPxRrQEBAQUAA4GNADCBiQKBgQCvRVUKp6pr4qBEnE9lviuyfiNq QtG/OCyBDXL4Bh3FmUzfNI+Z4Bh3FmUx+z2n0FCv/4BpgHTDl8D95NPopWVo1RH2 UfhyMd6dQ/x9T5m+y38JMzmSVAk+Fqu8ya18+yQVOEyEIx3Gxpsgegow33gcxfjK EsUgJHXcpw7OPxRrCQIDAQAB -----END PUBLIC KEY----- ' 

Можно ли сохранить структуру моего блока с помощью PyYAML?

Да, это возможно с помощью pyyaml , но вам нужно предоставить свои расширенные версии, по крайней мере, сканеров, парсеров и конструкторов, которые используются safe_load, Emitter, Serializer и Representer, используемые дампом, и предоставляют специализированные строки класс, который хранит информацию об этом оригинальном форматировании.

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

 import ruamel.yaml as yaml yaml_str = """\ pubkey: | -----BEGIN PUBLIC KEY----- MIGfMA0GCSq7OPxRrQEBAQUAA4GNADCBiQKBgQCvRVUKp6pr4qBEnE9lviuyfiNq QtG/OCyBDXL4Bh3FmUzfNI+Z4Bh3FmUx+z2n0FCv/4BpgHTDl8D95NPopWVo1RH2 UfhyMd6dQ/x9T5m+y38JMzmSVAk+Fqu8ya18+yQVOEyEIx3Gxpsgegow33gcxfjK EsUgJHXcpw7OPxRrCQIDAQAB -----END PUBLIC KEY----- """ data = yaml.load(yaml_str, Loader=yaml.RoundTripLoader) print(yaml.dump(data, Dumper=yaml.RoundTripDumper, indent=4)) 

дает тебе:

 pubkey: | -----BEGIN PUBLIC KEY----- MIGfMA0GCSq7OPxRrQEBAQUAA4GNADCBiQKBgQCvRVUKp6pr4qBEnE9lviuyfiNq QtG/OCyBDXL4Bh3FmUzfNI+Z4Bh3FmUx+z2n0FCv/4BpgHTDl8D95NPopWVo1RH2 UfhyMd6dQ/x9T5m+y38JMzmSVAk+Fqu8ya18+yQVOEyEIx3Gxpsgegow33gcxfjK EsUgJHXcpw7OPxRrCQIDAQAB -----END PUBLIC KEY----- 

по крайней мере, с Python 2.7 и 3.5.

Параметр indent=4 необходим, поскольку по умолчанию для RoundTripDumper два отступа пробела, а исходный отступ файла не сохраняется (это не облегчает повторный отступ файла YAML).

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