3

I am trying to use YAML for a python script. The YAML file I have written resembles this:

1:
  name: apple
  price: 5
3:
  name: orange
  price: 6
2:
  name: pear
  price: 2

When I load the YAML file using yaml.load the dictionary is sorted by the keys so it appears in order 1,2,3. How do I maintain the order 1,3,2?

Anthon
  • 69,918
  • 32
  • 186
  • 246
user35510
  • 179
  • 2
  • 14
  • Dictionaries in Python do not respect your original order, and will not keep a specific order. If you want an order dictionary, use an OrderedDict. – Christian Dean Sep 06 '16 at 19:24

1 Answers1

5

In the YAML specification it is explicitly stated that mapping keys have no order. In a file however they have. If you want a simple way to solve this replace PyYAML with ruamel.yaml (disclaimer: I am the author of that package, which is a superset of PyYAML) and use round_trip_load(), it will give you ordered dictionaries without the hassle of using single mapping item sequence elements that you need for specifying ordered dicts the "official" way.

import ruamel.yaml

yaml_str = """\
1:
  name: apple
  price: 5
3:
  name: orange
  price: 6
2:
  name: pear
  price: 2
"""

data = ruamel.yaml.round_trip_load(yaml_str)
for key in data:
    print(key)

gives

1
3
2

BTW PyYAML doesn't sort by the keys, that ordering is just a side-effect of calculating hashes and inserting integer keys 1, 2 , 3 in python dicts.

Anthon
  • 69,918
  • 32
  • 186
  • 246
  • Is ruamel.yaml available for windows or linux only? – user35510 Sep 06 '16 at 19:46
  • As the categories on PyPI indicate, it is OS independent. I primarily test and develop on Linux however, but I know from others that they use it on Windows and MacOS. – Anthon Sep 06 '16 at 19:49
  • I have successfully installed ruamel but get an error that it is expecting but found due to the """/ line found at the top of the file. What is the cause of this? – user35510 Sep 06 '16 at 20:38
  • The `"""` starts a multiline python string, which is useful if you want the file contents to be part of a program. You should however not put that into a YAML file, just use the file you have with the contents in your questionwith `data = ruamel.yaml.round_trip_load(open('your_file_name.yaml'))` – Anthon Sep 06 '16 at 21:15