2

转储 yaml 时如何保留键值缩进?我正在使用 ruamel yaml

代码:

in_str='''Pets:
    Cat:
       Tom
    Mouse:
       Jerry
    Dog:
       Scooby
       '''


import ruamel.yaml, sys
results = ruamel.yaml.load(in_str, ruamel.yaml.RoundTripLoader, preserve_quotes=True)
results['Pets']['Bird']='Tweety'
ruamel.yaml.dump(results, sys.stdout, ruamel.yaml.RoundTripDumper, default_flow_style=True,indent=2, block_seq_indent=2)

输出 :

Pets:
  Cat: Tom
  Mouse: Jerry
  Dog: Scooby
  Bird: Tweety

预期输出:

Pets:
    Cat:
       Tom
    Mouse:
       Jerry
    Dog:
       Scooby
    Bird:
       Tweety
4

1 回答 1

2

为了实现这一点,您必须Emitter在处理映射值时挂钩并让它插入换行符和适当的缩进。这可以使用您使用的旧式 API 来完成,但最好使用新的 ruamel.yaml API 来完成,它使您可以使用不同的值缩进序列和映射:

import sys
import ruamel.yaml
from ruamel.yaml.emitter import Emitter

class MyEmitter(Emitter):
    def expect_block_mapping_simple_value(self):
        # type: () -> None
        if getattr(self.event, 'style', None) != '?':
            # prefix = u''
            if self.indent == 0 and self.top_level_colon_align is not None:
                # write non-prefixed colon
                c = u' ' * (self.top_level_colon_align - self.column) + self.colon
            else:
                c = self.prefixed_colon
            self.write_indicator(c, False)
            # the next four lines force a line break and proper indent of the value
            self.write_line_break()
            self.indent += self.best_map_indent
            self.write_indent()
            self.indent -= self.best_map_indent
        self.states.append(self.expect_block_mapping_key)
        self.expect_node(mapping=True)


in_str='''\
Pets:
    Cat:
       Tom
    Mouse:
       - Jerry
       - 'Mickey'
    Dog:
       Scooby
       '''

yaml = ruamel.yaml.YAML()
yaml.Emitter = MyEmitter
yaml.indent(mapping=4, sequence=2, offset=0)
yaml.preserve_quotes = True
results = yaml.load(in_str)
results['Pets']['Bird']='Tweety'
yaml.dump(results, sys.stdout)

这给出了:

Pets:
    Cat:
        Tom
    Mouse:
        - Jerry
        - 'Mickey'
    Dog:
        Scooby
    Bird:
        Tweety

注意事项:

  • 您只需要处理简单的标量值(与映射/序列相反,它们已经在块序列“模式”中“推送”到下一行)
  • expect_block_mapping_simple_value源代码复制并添加了几行。目前没有“钩子”可以在不复制一些代码的情况下执行此操作。
  • 如果您有序列并且需要不同的缩进,您可以使用sequenceoffset值。yaml.indent()
  • 所有这些都假设一致的缩进,不保留单独的缩进(即,如果某些值的缩进多于或少于四个位置,它们将最终得到 4 个位置)。
于 2017-12-30T06:51:21.987 回答