-
-
Save oglops/c70fb69eef42d40bed06 to your computer and use it in GitHub Desktop.
#!/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)) | |
# 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)) |
NB: use items()
instead of iteritems()
for Python 3.
Thanks!
Very useful. Thank you!
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
nice! I just need the loader part, so this is very simple (compared to some other approaches..)
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)
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/
Thank you very much! Very useful!
great work 👍