如何在转储yaml时保留键值的缩进

时间:2017-12-29 23:18:38

标签: python python-2.7 yaml pyyaml ruamel.yaml

如何在转储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

1 个答案:

答案 0 :(得分: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并添加几行。目前没有" hook"这样做而不重复一些代码。
  • 如果您有序列并且需要不同的缩进,则可以使用sequence的{​​{1}}和offset值。
  • 所有这些都假定一致的缩进,不保留个别缩进(即如果某些值缩进的位数多于或少于四个位置,则它们最终会有4个位置)。