ruamel.yaml equivalent of sort_keys?

python, ruamel.yaml

Solution

You need some recursive function that handles mappings/dicts, sequence/list:

import sys
import ruamel.yaml

CM = ruamel.yaml.comments.CommentedMap

yaml = ruamel.yaml.YAML()

data = dict(a=1, c=dict(b=2, a=1), b=[2, dict(e=6, d=5), 4])
yaml.dump(data, sys.stdout)

def rec_sort(d):
    try:
        if isinstance(d, CM):
            return d.sort()
    except AttributeError:
        pass
    if isinstance(d, dict):
        # could use dict in newer python versions
        res = ruamel.yaml.CommentedMap()
        for k in sorted(d.keys()):
            res[k] = rec_sort(d[k])
        return res
    if isinstance(d, list):
        for idx, elem in enumerate(d):
            d[idx] = rec_sort(elem)
    return d

print('---')

yaml.dump(rec_sort(data), sys.stdout)

which gives:

a: 1
c:
  b: 2
  a: 1
b:
- 2
- e: 6
  d: 5
- 4
---
a: 1
b:
- 2
- d: 5
  e: 6
- 4
c:
  a: 1
  b: 2

The commented map is the structure ruamel.yaml uses when doing a round-trip (load+dump) and round-tripping is designed to keep the keys in the order that they were during loading.

The above should do a reasonable job preserving comments on mappings/sequences when you load `data` from a commented YAML file

Problem

I'm trying to dump a Python dict to a YAML file using `ruamel.yaml`. I'm familiar with the `json` module's interface, where pretty-printing a dict is as simple as ``` import json with open('outfile.json', 'w') as f: json.dump(mydict, f, indent=4, sort_keys=True) ``` With `ruamel.yaml`, I've gotten as far as ``` import ruamel.yaml with open('outfile.yaml', 'w') as f: ruamel.yaml.round_trip_dump(mydict, f, indent=2) ``` but it doesn't seem to support the `sort_keys` option. `ruamel.yaml` also doesn't seem to have any exhaustive docs, and searching Google for "ruamel.yaml sort" or "ruamel.yaml alphabetize" didn't turn up anything at the level of simplicity I'd expect. Is there a one-or-two-liner for pretty-printing a YAML file with sorted keys? (Note that I need the keys to be alphabetized down through the whole container, recursively; just alphabetizing the top level is not good enough.) Notice that if I use `round_trip_dump`, the keys are not sorted; and if I use `safe_dump`, the output is not "YAML-style" (or more importantly "Kubernetes-style") YAML. I don't want `[]` or `{}` in my output. ``` $ pip freeze | grep yaml ruamel.yaml==0.12.5 $ python >>> import ruamel.yaml >>> mydict = {'a':1, 'b':[2,3,4], 'c':{'a':1,'b':2}} >>> print ruamel.yaml.round_trip_dump(mydict) # right format, wrong sorting a: 1 c: a: 1 b: 2 b: - 2 - 3 - 4 >>> print ruamel.yaml.safe_dump(mydict) # wrong format, right sorting a: 1 b: [2, 3, 4] c: {a: 1, b: 2} ```

Original source