PYYAML:YAML.LOAD()调用的项目的控制排序



我有一个yaml设置文件,该文件在db中创建一些记录:

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

当我用 setter3 和DB中的记录更新此文件时:

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保持在db ...和设置3只是将其附加到yaml.load()的结尾很重要。ID不会混淆DB中已经存在的任何记录...目前,每次我添加另一个设置并调用yaml.load()记录以不同的顺序加载,从而导致不同的ID。我欢迎任何想法;)

编辑:我已经遵循了 abarnert 提示,并接受了此GIST https://gist.github.com/8444388

效果按预期的效果,谢谢!

我的项目oyaml是PYYAML的置换式替代品,它将将映射加载到collections.OrderedDict而不是常规dicts中。只需pip安装它并按照普通方式使用 - 在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]')]))])

请注意,如果stdlib dict是保留订单(python> = 3.7,cpython> = 3.6),则oyaml将使用普通的dict。

您现在可以使用 ruaml.yaml 为此。

来自https://pypi.python.org/pypi/ruamel.yaml:

ruamel.yaml是支持往返的yaml解析器/发射器 保存评论,SEQ/MAP FLOW样式和地图密钥顺序

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 s的tuple,但是您可以轻松编写construct_ordereddict并获得OrderedDict。您还可以编写一个代表,如果您需要输出和输入,将OrdereredDict对象存储为!omap s。

如果您真的想挂接pyyAml以使其使用OrderedDict而不是dict用于默认映射,则如果您已经直接在Parser对象上工作,则很容易做到,但是如果您坚持使用该映射高级便利方法。幸运的是,上述机票具有您可以使用的实现。只需记住,您不再使用真实的YAML,而是一个变体,因此处理您的文件的任何其他软件都可以并且可能会破坏。

对于给定的单个项目,该项目已知是有序的字典,只需制作列表的项目和使用的集合。

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'])

上次我听到的,pyyaml不支持这一点,尽管它可能很容易修改它接受字典或字典式对象作为起点。

Div>

最新更新