9

Example from Using YAML with Python

Original YAML file contains this

# tree format
treeroot:
    branch1:
        name: Node 1
        branch1-1:
            name: Node 1-1
    branch2:
        name: Node 2
        branch2-1:
            name: Node 2-1

After loading the content from the file using yaml.load() , and dump it into a new YAML file, I get this instead:

# tree format
treeroot:
    branch1:
        branch1-1: {name:Node 1-1}
        name: Node 1
    branch2:
        branch2-1: {name: Node 2-1}
        name: Node 2

What is the proper way of building up a YAML file straight from pure python? I don't want to write string myself. I want to build the dictionary and list.


Partial...

dataMap = {'treeroot':
               {'branch2': 
                 {'branch1-1': 
                  {'name': 'Node 1-1'},   # should be its own level
                  'name': 'Node 1'
                 }
               }
          }
Anthon
  • 69,918
  • 32
  • 186
  • 246
CppLearner
  • 16,273
  • 32
  • 108
  • 163
  • 1
    Are you asking how you can guarantee getting the same file out as in? If so, there is no guarantee, because dictionaries have no predefined order. – Nate Feb 03 '12 at 20:51
  • @Nate Right, that's my intention. I understand that. I edited and provided part of the structure. Yaml dumps can't parase the inner {name: Node 1-1} into another level.... – CppLearner Feb 03 '12 at 21:02

3 Answers3

8

OKay. I just double checked the documentation. We need this at the end of the yaml.dump(data, optional_args)

The fix is this

yaml.dump(dataMap, f, default_flow_style=False)

where dataMap is the source yaml.load() and f is the file to be written to.

CppLearner
  • 16,273
  • 32
  • 108
  • 163
2

Assuming you are using PyYAML as you probably are, the output you show is not copy-paste of what a yaml.dump() generated as it includes a comment, and PyYAML doesn't write those.

If you want to preserve that comment, as well as e.g the key ordering in the file (nice when you store the file in a revision control system) use ¹:

import ruamel.yaml as yaml

yaml_str = """\
# tree format
treeroot:
    branch1:
        name: Node 1
        branch1-1:
            name: Node 1-1   # should be its own level
    branch2:
        name: Node 2
        branch2-1:
            name: Node 2-1
"""

data = yaml.load(yaml_str, Loader=yaml.RoundTripLoader)
print yaml.dump(data, Dumper=yaml.RoundTripDumper, indent=4)

which gets you exactly the input:

# tree format
treeroot:
    branch1:
        name: Node 1
        branch1-1:
            name: Node 1-1   # should be its own level
    branch2:
        name: Node 2
        branch2-1:
            name: Node 2-1

¹ This was done using ruamel.yaml an enhanced version of PyYAML of which I am the author.

Anthon
  • 69,918
  • 32
  • 186
  • 246
1

Your first and second listings are equivalent, just different notation.

See: http://en.wikipedia.org/wiki/YAML#Associative_arrays and http://pyyaml.org/wiki/PyYAMLDocumentation#Dictionarieswithoutnestedcollectionsarenotdumpedcorrectly

nisc
  • 4,222
  • 4
  • 29
  • 34