python yaml.dump bad indentation

前端 未结 2 1450
眼角桃花
眼角桃花 2021-02-05 03:27

I\'m executing the following python code:

import yaml


foo = {
    \'name\': \'foo\',
    \'my_list\': [{\'foo\': \'test\', \'bar\': \'test2\'}, {\'foo\': \'tes         


        
相关标签:
2条回答
  • 2021-02-05 04:02

    Your output, as shown, is incomplete as print(yaml.dump()) gives you an extra empty line after name: foo. It is also slower and uses more memory than directly streaming to sys.stdout.

    You are probably using PyYAML and, apart from only supporting the outdated YAML 1.1 specification, it is very limited in control over the dumped YAML.

    I suggest you use ruamel.yaml (disclaimer: I am the author of that package), where you can specify identation separately for mappings and sequences and also indicate how far to offset the dash within the indent before the sequence element:

    import sys
    import ruamel.yaml
    
    foo = {
        'name': 'foo',
        'my_list': [{'foo': 'test', 'bar': 'test2'}, {'foo': 'test3', 'bar': 'test4'}],
        'hello': 'world'
    }
    
    
    yaml = ruamel.yaml.YAML()
    yaml.indent(sequence=4, offset=2)
    yaml.dump(foo, sys.stdout)
    

    which gives:

    name: foo
    my_list:
      - foo: test
        bar: test2
      - foo: test3
        bar: test4
    hello: world
    

    Please note that the order of the keys is implementation dependent (but can be controlled, as ruamel.yaml can round-trip the above without changes).

    0 讨论(0)
  • 2021-02-05 04:05

    This ticket suggests the current implementation correctly follows the spec:

    The “-”, “?” and “:” characters used to denote block collection entries are perceived by people to be part of the indentation. This is handled on a case-by-case basis by the relevant productions.

    On the same thread, there is also this code snippet (modified to fit your example) to get the behavior you are looking for:

    import yaml
    
    class MyDumper(yaml.Dumper):
    
        def increase_indent(self, flow=False, indentless=False):
            return super(MyDumper, self).increase_indent(flow, False)
    
    foo = {
        'name': 'foo',
        'my_list': [
            {'foo': 'test', 'bar': 'test2'},
            {'foo': 'test3', 'bar': 'test4'}],
        'hello': 'world',
    }
    
    print yaml.dump(foo, Dumper=MyDumper, default_flow_style=False)
    
    0 讨论(0)
提交回复
热议问题