Skip to content

Instantly share code, notes, and snippets.

@enaeseth
Created February 25, 2011 19:54
Show Gist options
  • Save enaeseth/844388 to your computer and use it in GitHub Desktop.
Save enaeseth/844388 to your computer and use it in GitHub Desktop.
Load YAML mappings as ordered dictionaries
import yaml
import yaml.constructor
try:
# included in standard lib from Python 2.7
from collections import OrderedDict
except ImportError:
# try importing the backported drop-in replacement
# it's available on PyPI
from ordereddict import OrderedDict
class OrderedDictYAMLLoader(yaml.Loader):
"""
A YAML loader that loads mappings into ordered dictionaries.
"""
def __init__(self, *args, **kwargs):
yaml.Loader.__init__(self, *args, **kwargs)
self.add_constructor(u'tag:yaml.org,2002:map', type(self).construct_yaml_map)
self.add_constructor(u'tag:yaml.org,2002:omap', type(self).construct_yaml_map)
def construct_yaml_map(self, node):
data = OrderedDict()
yield data
value = self.construct_mapping(node)
data.update(value)
def construct_mapping(self, node, deep=False):
if isinstance(node, yaml.MappingNode):
self.flatten_mapping(node)
else:
raise yaml.constructor.ConstructorError(None, None,
'expected a mapping node, but found %s' % node.id, node.start_mark)
mapping = OrderedDict()
for key_node, value_node in node.value:
key = self.construct_object(key_node, deep=deep)
try:
hash(key)
except TypeError, exc:
raise yaml.constructor.ConstructorError('while constructing a mapping',
node.start_mark, 'found unacceptable key (%s)' % exc, key_node.start_mark)
value = self.construct_object(value_node, deep=deep)
mapping[key] = value
return mapping
if __name__ == '__main__':
import textwrap
sample = """
one:
two: fish
red: fish
blue: fish
two:
a: yes
b: no
c: null
"""
data = yaml.load(textwrap.dedent(sample), OrderedDictYAMLLoader)
assert type(data) is OrderedDict
print data
@alborzs
Copy link

alborzs commented Jun 3, 2013

Hi,
I have a big code base and so far I used vanilla yaml load like this yaml.load(s, Loader=yaml.BaseLoader)
I tried your OrderedDictYAMLLoader but I pretty much get nothing from load now.
what is the exact diffrences, have you tested this in a real application maybe with nested dictionaries of diffrent length?

thanks

@randyesq
Copy link

Is there a license for this code snippet? Can I use it?

@davidnewhall
Copy link

Licensing this with anything would sure help out the commercial Internet community.

@wimglenn
Copy link

MIT license on oyaml here https://github.com/wimglenn/oyaml

@caiolang
Copy link

caiolang commented Sep 18, 2024

From PyYAML 5.1 on, a dictionary can be dumped without reordering keys with:

yaml.dump(data, sort_keys=False)

Saw this on stack overflow and it works, the docs don't seem to be updated though...

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