Обновление: В Python 3.6+ вам, вероятно, вообще не нужен OrderedDict
из-за новой реализации dict , которая некоторое время использовалась в pypy (хотя рассмотрены детали реализации CPython на данный момент).
Обновление: В Python 3.7+, природа сохранения объектов ввода в порядке вставки была объявлена официальной частью спецификации языка Python , см. Что такое Новое в Python 3.7 .
Мне нравится @James ' решение за его простоту. Однако он меняет глобальный класс yaml.Loader
по умолчанию, что может привести к неприятным побочным эффектам. Особенно при написании библиотечного кода это плохая идея. Кроме того, он не работает напрямую с yaml.safe_load()
.
К счастью, решение можно улучшить без особых усилий:
import yaml
from collections import OrderedDict
def ordered_load(stream, Loader=yaml.Loader, object_pairs_hook=OrderedDict):
class OrderedLoader(Loader):
pass
def construct_mapping(loader, node):
loader.flatten_mapping(node)
return object_pairs_hook(loader.construct_pairs(node))
OrderedLoader.add_constructor(
yaml.resolver.BaseResolver.DEFAULT_MAPPING_TAG,
construct_mapping)
return yaml.load(stream, OrderedLoader)
# usage example:
ordered_load(stream, yaml.SafeLoader)
Для сериализации я не знаю очевидного обобщения, но по крайней мере это не должно иметь побочных эффектов:
def ordered_dump(data, stream=None, Dumper=yaml.Dumper, **kwds):
class OrderedDumper(Dumper):
pass
def _dict_representer(dumper, data):
return dumper.represent_mapping(
yaml.resolver.BaseResolver.DEFAULT_MAPPING_TAG,
data.items())
OrderedDumper.add_representer(OrderedDict, _dict_representer)
return yaml.dump(data, stream, OrderedDumper, **kwds)
# usage:
ordered_dump(data, Dumper=yaml.SafeDumper)