PyYaml сбрасывает вещи задом наперед - PullRequest
1 голос
/ 31 марта 2012

Итак, у меня есть файл yaml с множеством пустяковых вопросов и списком ответов.Однако всякий раз, когда я пытаюсь загрузить этот файл и вывести содержимое в python с помощью pyyaml, он сбрасывает их назад.Я не уверен, что это мой файл 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"]}

Когда я использую yaml.dump () в этом словаре Python, он выдает это -

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 ]

6 голосов
/ 22 декабря 2012

У меня здесь несколько другой ответ. Ответ 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 диктовку или что-либо с атрибутом items, он будет сортировать элементы перед сбросом, но если вы дадите ему выходные данные items () (например, список (ключ , значение) кортежи), это не будет. Таким образом, мы можем использовать

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. Казалось, что это было в первую очередь важно для читабельности.

4 голосов
/ 26 июня 2013

Если порядок, если предпочтительнее, в дампе, можно использовать код ниже

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 голосов
/ 31 марта 2012

Ассоциативные массивы YAML (и словари python) не сохраняют порядок своих элементов.

Однако, если заказ импортируется, YAML определяет упорядоченную карту !!omap, которую PyYAML по умолчанию разбирает в список кортежей, например:

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

Этот ответ дает некоторые подробности о том, как загрузить !!omap в них в Python OrderedDict .

1 голос
/ 31 марта 2012

Если он загружает их как словарь, их порядок произвольный. Словари не заказанные контейнеры.

...