PyYAML:由yaml.load称为项目的控制排序()(PyYAML : Control orde

2019-08-02 11:55发布

我有在数据库创建一些记录YAML设置文件:

setting1:
  name: [item,item]
  name1: text
anothersetting2:
  name: [item,item]
  sub_setting:
      name :[item,item]

当我与setting3更新此文件并重新生成数据库记录:

import yaml
fh = open('setting.txt', 'r')
setting_list = yaml.load(fh)
for i in setting_list:
    add_to_db[i]

这是至关重要的,他们的设置(DB ID号)的顺序停留每次同他们的IM向addig分贝......和setting3只是被追加到yaml.load()的末尾,以便其ID没有按'牛逼混淆它们已经在DB的任何记录......此刻我每次添加其他设置和调用yaml.load()记录获取加载不同的顺序导致不同的ID。 我欢迎任何想法;)

编辑:我跟着abarnert技巧,把这个要点https://gist.github.com/844388

按预期工作的感谢!

Answer 1:

所述YAML规范明确地说,一个映射内的键顺序是“表示细节”不能依靠。 所以,如果它依靠的映射,你会使用有效的YAML,如果在所有可能的好得多设置文件已经无效。

当然YAML是可扩展的,并没有什么,从添加“命令映射”类型的设置文件阻止你。 例如:

!omap setting1:
  name: [item,item]
  name1: text
!omap anothersetting2:
  name: [item,item]
  !omap sub_setting:
      name :[item,item]

你没有提到这yaml您正在使用的模块。 有一个在标准库中没有这样的模块,并有刚刚PyPI上至少有两个包,提供与该名称的模块。 不过,我要去猜它的PyYAML,因为据我所知,这是最流行的。

上述延伸部是易与PyYAML解析。 见http://pyyaml.org/ticket/29 :

def omap_constructor(loader, node):
    return loader.construct_pairs(node)
yaml.add_constructor(u'!omap', omap_constructor)

现在,而不是:

{'anothersetting2': {'name': ['item', 'item'],
  'sub_setting': 'name :[item,item]'},
 'setting1': {'name': ['item', 'item'], 'name1': 'text'}}

你会得到这样的:

(('anothersetting2', (('name', ['item', 'item']),
  ('sub_setting', ('name, [item,item]'),))),
 ('setting1', (('name', ['item', 'item']), ('name1', 'text'))))

当然,这给你一个tuple键值的tuple S,但你可以很容易地编写一个construct_ordereddict,并得到一个OrderedDict代替。 您也可以编写存储申述OrdereredDict对象作为!omap S,如果需要输出和输入。

如果你真的要挂钩PyYAML,使其使用OrderedDict而不是dict为默认映射,它,如果你想坚持的高层是很容易做到,如果你已经在解析器对象直接合作,但较难方便的方法。 幸运的是,上述联票有可以使用的实现。 只要记住,你不使用真正的YAML了,但一个变体,使之与您的文件可以涉及任何其他软件,并有可能将,休息。



Answer 2:

我的项目oyaml是一个简易替换为PyYAML,这将地图加载到collections.OrderedDict代替常规类型的字典。 只要点子安装和正常使用 - 适用于Python的3和Python 2两。

演示你的例子:

>>> import oyaml as yaml  # pip install oyaml
>>> yaml.load('''setting1:
...   name: [item,item]
...   name1: text
... anothersetting2:
...   name: [item,item]
...   sub_setting:
...       name :[item,item]''')
OrderedDict([('setting1',
              OrderedDict([('name', ['item', 'item']), ('name1', 'text')])),
             ('anothersetting2',
              OrderedDict([('name', ['item', 'item']),
                           ('sub_setting', 'name :[item,item]')]))])


Answer 3:

您现在可以使用ruaml.yaml这一点。

从https://pypi.python.org/pypi/ruamel.yaml :

ruamel.yaml是YAML解析器/发射器,支持的意见,以次/地图流量风格往返保存,并映射键顺序



Answer 4:

对于被称为一个给定的单个项目是一个有序字典只是做一个列表的项目和使用collections.OrderedDict:

setting1:
  - name: [item,item]
  - name1: text
anothersetting2:
  - name: [item,item]
  - sub_setting:
      name :[item,item]

import collections
import yaml
fh = open('setting.txt', 'r')
setting_list = yaml.load(fh)

setting1 = collections.OrderedDict(list(x.items())[0] for x in setting_list['setting1'])


Answer 5:

上次我听说,PyYAML不支持这一点,虽然它可能会很容易修改它以接受一本字典或词典类对象作为一个起点。



文章来源: PyYAML : Control ordering of items called by yaml.load()
标签: python pyyaml