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

问题描述 投票:2回答:1

如何在转储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
python python-2.7 yaml pyyaml ruamel.yaml
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并添加几行。目前没有“钩子”可以做到这一点而不重复一些代码。
  • 如果你有序列并且需要不同的缩进,你可以使用sequenceoffsetyaml.indent()值。
  • 所有这些都假定一致的缩进,不保留单个缩进(即,如果某些值缩进多于或少于四个位置,它们最终会有4个位置)。
© www.soinside.com 2019 - 2024. All rights reserved.