在序列化Python字典时,如何控制PyYaml输出键/值对的顺序?
我在Python脚本中使用Yaml作为简单的序列化格式.我的Yaml序列化对象代表了一种"文档",因此为了最大限度地方便用户,我希望我的对象的"名称"字段首先出现在文件中.当然,由于我的对象返回的值__getstate__
是字典,并且Python字典是无序的,因此"name"字段将被序列化为输出中的随机位置.
例如
>>> import yaml
>>> class Document(object):
... def __init__(self, name):
... self.name = name
... self.otherstuff = 'blah'
... def __getstate__(self):
... return self.__dict__.copy()
...
>>> doc = Document('obj-20111227')
>>> print yaml.dump(doc, indent=4)
!!python/object:__main__.Document
otherstuff: blah
name: obj-20111227
Run Code Online (Sandbox Code Playgroud)
Cer*_*rin 18
花了几个小时挖掘PyYAML文档和故障单,但我最终发现了这个评论,它列出了一些概念验证代码,用于将OrderedDict序列化为普通的YAML映射(但保持顺序).
例如,应用于我的原始代码,解决方案看起来像:
>>> import yaml
>>> from collections import OrderedDict
>>> def dump_anydict_as_map(anydict):
... yaml.add_representer(anydict, _represent_dictorder)
...
>>> def _represent_dictorder( self, data):
... if isinstance(data, Document):
... return self.represent_mapping('tag:yaml.org,2002:map', data.__getstate__().items())
... else:
... return self.represent_mapping('tag:yaml.org,2002:map', data.items())
...
>>> class Document(object):
... def __init__(self, name):
... self.name = name
... self.otherstuff = 'blah'
... def __getstate__(self):
... d = OrderedDict()
... d['name'] = self.name
... d['otherstuff'] = self.otherstuff
... return d
...
>>> dump_anydict_as_map(Document)
>>> doc = Document('obj-20111227')
>>> print yaml.dump(doc, indent=4)
!!python/object:__main__.Document
name: obj-20111227
otherstuff: blah
Run Code Online (Sandbox Code Playgroud)
小智 5
我认为问题在于您何时转储数据。我查看了 PyYaml 的代码,有一个名为 的可选参数sort_keys
,将该值设置为False
似乎可以解决问题。
新解决方案(截至2020 年和 PyYAML 5.1)
您只需使用即可按当前顺序转储字典
yaml.dump(data, default_flow_style=False, sort_keys=False)
Run Code Online (Sandbox Code Playgroud)