Skip to content

Instantly share code, notes, and snippets.

@oglops
Last active January 25, 2023 11:08
Show Gist options
  • Save oglops/c70fb69eef42d40bed06 to your computer and use it in GitHub Desktop.
Save oglops/c70fb69eef42d40bed06 to your computer and use it in GitHub Desktop.
write to and load from yaml file with OrderedDict
#!/usr/bin/env python
try:
# for python newer than 2.7
from collections import OrderedDict
except ImportError:
# use backport from pypi
from ordereddict import OrderedDict
import yaml
# try to use LibYAML bindings if possible
try:
from yaml import CLoader as Loader, CDumper as Dumper
except ImportError:
from yaml import Loader, Dumper
from yaml.representer import SafeRepresenter
_mapping_tag = yaml.resolver.BaseResolver.DEFAULT_MAPPING_TAG
def dict_representer(dumper, data):
return dumper.represent_dict(data.items())
def dict_constructor(loader, node):
return OrderedDict(loader.construct_pairs(node))
Dumper.add_representer(OrderedDict, dict_representer)
Loader.add_constructor(_mapping_tag, dict_constructor)
Dumper.add_representer(str,
SafeRepresenter.represent_str)
Dumper.add_representer(unicode,
SafeRepresenter.represent_unicode)
# output = yaml.dump(data, Dumper=Dumper, default_flow_style=False)
# data = yaml.load(stream, Loader=Loader)
# abc:
# x:
# 0: null
# y:
# 1: null
yml_dict = OrderedDict(
abc=OrderedDict(
[('x', OrderedDict([(0, None)])), ('y', OrderedDict([(1, None)]))]))
import json
print(json.dumps(yml_dict, indent=2))
print
# dump ordereddict to yaml
output = yaml.dump(yml_dict, Dumper=Dumper, default_flow_style=False)
print output
# directly write to a file object to save memory.
with open('result.yml', 'w') as f:
yaml.dump(yml_dict, f, default_flow_style=False)
import yaml
from yaml import SafeDumper, Dumper, SafeLoader
from collections import OrderedDict
class OrderedDumper(SafeDumper):
def __init__(self, *args, **kwargs):
super(OrderedDumper, self).__init__(*args, **kwargs)
represent_dict_order = lambda self, data: self.represent_mapping(yaml.resolver.BaseResolver.DEFAULT_MAPPING_TAG, data.items())
self.add_representer(OrderedDict, represent_dict_order)
data = OrderedDict([(2, 'b'), (1, 'a'), (3, [{'children': [{4: 'c'}, {5: 'd'}]}])])
print(yaml.dump(data, Dumper=OrderedDumper))
class OrderedLoader(SafeLoader):
def __init__(self, *args, **kwargs):
super(OrderedLoader, self).__init__(*args, **kwargs)
construct_dict_order = lambda self, data: OrderedDict(self.construct_pairs(data))
self.add_constructor(yaml.resolver.BaseResolver.DEFAULT_MAPPING_TAG, construct_dict_order)
with open('test.yaml') as f:
d = yaml.load(f, Loader=OrderedLoader)
print(d)
# pretty print ordered dict
import json
print(json.dumps(d, indent=4))
@alignan
Copy link

alignan commented Jan 20, 2018

Thanks!

@cirrus-wizard
Copy link

Very useful. Thank you!

@krishnag9
Copy link

krishnag9 commented Dec 5, 2018

Very useful for Python 2.7.
Since unicode is removed from python 3, I have faced an error at Dumper.add_representer(unicode, SafeRepresenter.represent_unicode). I have removed that line. But the generated yaml file contains !!python/tuple and &id001 here and there. Please help me in resolving this

@srepmub
Copy link

srepmub commented Jul 30, 2019

nice! I just need the loader part, so this is very simple (compared to some other approaches..)

@RubendeBruin
Copy link

RubendeBruin commented Oct 11, 2020

For saving OrderedDict files I had to change iteritems() to items()


from yaml import CDumper as Dumper

def dict_representer(dumper, data):
     return dumper.represent_dict(data.items())

Dumper.add_representer(OrderedDict, dict_representer)

  s = yaml.dump(data, explicit_start=True, Dumper=Dumper)

@oglops
Copy link
Author

oglops commented Jul 20, 2022

The original code changes yaml behavior globally, if you are working on a library, a better approach is to customize dumper/loader subclass
https://ilmvfx.wordpress.com/2022/07/20/yaml-json-tree-serialize-keep-order/

@asterios-pantousas
Copy link

Thank you very much! Very useful!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment