PyYaml向后倾倒东西

时间:2012-03-31 00:14:08

标签: python yaml pyyaml

所以我有一个yaml文件,其中包含许多琐事问题和答案列表。但是,每当我尝试加载此文件并使用pyyaml将内容转储到python中时,它会向后转储它们。我不确定这是我的yaml文件还是我的库有问题。

假设我的一个问题/答案对在yaml文件中看起来像这样 -

{"question": "What is the name of this sequence of numbers: 1, 1, 2, 3, 5, 8, 13, ...", 
 "answer": ["The Fibonacci Sequence", "The Padovan Sequence", "The Morris Sequence"]}

当我在那个python字典上使用yaml.dump()时,它会转储 -

answer: [fibonacci, padovan, morris]\nquestion: 'what sequence is this: 1, 1, 2, 3, 5, 8, 13, ...'\n"

我在期待这个 -

- question: "What is the name of this sequence of numbers: 1, 1, 2, 3, 5, 8, 13, ..."
  answer: ["The Fibonacci Sequence", "The Padovan Sequence", "The Morris Sequence"]

我在这里做错了吗?

4 个答案:

答案 0 :(得分:6)

我在这里有一个不同的答案。如果由于可读性以外的原因,元素的顺序对您很重要,那么dbaupp的答案是正确的。如果你想在回答前显示问题的唯一原因是为了使文件更易于阅读,那么你不需要使用!! omap,而是可以使用自定义代表来获得你想要的顺序。

首先,你在没有 - 前面的转储器转储的问题是因为你只是转储一个映射,而不是它们的列表。把你的词典放在一个列表中,这将被修复。所以我们从:

开始
d = [{"question": "What is the name of this sequence of numbers: 1, 1, 2, 3, 5, 8, 13, ...", 
 "answer": ["The Fibonacci Sequence", "The Padovan Sequence", "The Morris Sequence"]}]

现在我们有一个我们想要输出的特定订单,所以我们将指定它,并使用该顺序转换为OrderedDict:

from collections import OrderedDict
order = ['question', 'answer']
do = [ OrderedDict( sorted( z.items(), key=lambda x: order.index(x[0]) ) ) for z in d ]

接下来,我们需要做到这一点,以便PyYAML知道如何处理OrderedDict。在这种情况下,我们不希望它是一个!! omap,我们只想要一个具有特定顺序的映射。对于某些我不清楚的动机,如果你给dumper.represent_mapping一个dict,或任何带有items属性的东西,它会在转储前对项进行排序,但是如果你给它输出items()(例如,一个列表的(key) ,值)元组),它不会。因此我们可以使用

def order_rep(dumper, data):
    return dumper.represent_mapping( u'tag:yaml.org,2002:map', data.items(), flow_style=False )
yaml.add_representer( OrderedDict, order_rep )

然后,print yaml.dump(do)的输出结果为:

- question: 'What is the name of this sequence of numbers: 1, 1, 2, 3, 5, 8, 13, ...'
  answer: [The Fibonacci Sequence, The Padovan Sequence, The Morris Sequence]

有许多不同的方法可以做到这一点。使用OrderedDict实际上根本不是必需的,你只需要问题/答案对就可以为某个类编写代表。

再一次,确实意识到这只是为了人类的可读性和美学目的。这里的顺序不具有任何YAML意义,就像你使用!! omap一样。为了便于阅读,这似乎对您来说非常重要。

答案 1 :(得分:4)

如果转储中的首选顺序,可以使用下面的代码

import yaml

class MyDict(dict):
   def to_omap(self):
      return [('question', self['question']), ('answer', self['answer'])]

def represent_omap(dumper, data):
   return dumper.represent_mapping(u'tag:yaml.org,2002:map', data.to_omap())

yaml.add_representer(MyDict, represent_omap)

questions = [
   MyDict({'answer': 'My name is Bob.', 'question': 'What is your name?'}),
   MyDict({'question': 'How are you?', 'answer': 'I am fine.'}),
]
print yaml.dump(questions, default_flow_style=False)

输出结果为:

- question: What is your name?
  answer: My name is Bob.
- question: How are you?
  answer: I am fine.

答案 2 :(得分:2)

YAML关联数组(和python词典)不保留其元素的顺序。

但是,如果订单是导入的,那么YAML定义了ordered map !!omap,默认情况下PyYAML会解析为元组列表,例如:

>>> yaml.load('''!!omap
... - a: foo
... - b: bar''')
[('a','foo'),('b','bar')]

This answer提供了有关如何将!!omap加载到Python OrderedDict中的详细信息。

答案 3 :(得分:1)

如果它将它们作为字典加载,则它们的顺序是任意的。字典不是有序容器。