在Python中控制Yaml序列化顺序

Cer*_*rin 13 python yaml

在序列化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似乎可以解决问题。

  • 这个答案就是我一直在寻找的。如果您将“sort_keys”设置为“False”,PyYaml 将尊重您的字典顺序。```python yaml.dump(数据,文件,sort_keys=False) ``` (2认同)

Joh*_*n D 5

新解决方案(截至2020 年和 PyYAML 5.1)

您只需使用即可按当前顺序转储字典

yaml.dump(data, default_flow_style=False, sort_keys=False)
Run Code Online (Sandbox Code Playgroud)