2016-03-14 1 views
1

J'ai un python ordonné dictionnaire comme,décharge YAML pour les listes Python utilise le format en ligne au lieu de hypen + espace

from collections import OrderedDict 
a = OrderedDict() 
a['name'] = 'hello' 
a['msgs'] = ['hello', 'world'] 

Et je suis en train de convertir à la syntaxe YAML que,

import yaml 
with open("b.yaml", 'w') as stream: 
    stream.write(yaml.dump(a)) 

imprime ,

!!python/object/apply:collections.OrderedDict 
- - [name, hello] 
    - - msgs 
    - [hello, world] 

Alors, je me attendais à un format YAML plus simple que,

name : hello 
msgs: 
    - hello 
    - world 

Comment puis-je forcer YAML à imprimer des éléments de liste avec la notation hypen + space au lieu de JSON comme notation ?

Pourquoi PyYAML imprime-t-il un article dict ordonné comme [name, hello] et non comme name : hello?

Répondre

3

Votre question porte à confusion. En commençant par votre exemple initial, vous avez besoin d'un codage explicite pour convertir votre a = {...} en OrderedDict. Prenez cela de côté, c'est votre sortie prévue:

>>> a = { 
... "name" : 'hello', 
... "msgs" : ['hello', 'world'] 
... } 
>>> print(yaml.dump(a)) 
msgs: [hello, world] 
name: hello 

Ce qui n'est pas exactement ce que vous vouliez. Si vous lisez le FAQ spécifiquement sur cette question, vous constaterez que le passage à default_flow_style à dump donnera les résultats souhaités

>>> print(yaml.dump(a, default_flow_style=False)) 
msgs: 
- hello 
- world 
name: hello 

Quant à savoir pourquoi OrderedDict à venir comme ça, cela est discuté dans la section YAML tags and Python types dans la documentation . En résumé, ceci est fait en considération du protocole pickle de Python, et puisque OrderedDict sont list s en interne (dont list sont commandés; dict s sont non ordonnés par définition), il obtient la représentation semblable à une liste.

+0

merci man ... yup, maintenant j'ai fait mon python dict comme un 'OrderedDict' ... –

+0

S'il vous plaît noter que les clés de votre fichier ne sont pas dans l'ordre prévu, ce qui peut entraîner des problèmes si ce fichier est cochée dans un système de contrôle de révision. De plus, l'indentation des séquences n'est pas celle attendue par l'OP, mais alignée avec la clé 'msgs'. – Anthon

2

Si vous ne lisez pas la spécification YAML, vous vous attendez à ce que les mappages dans les fichiers YAML soient ordonnés, car la représentation de texte dans un fichier YAML est ordonnée. Malheureusement cette hypothèse intuitive est fausse, le YAML 1.2 indique explicitement que ceci [doit être interprété comme] un non ordonné ensemble de clé: paires de valeurs. Ceci permet de comparer des fichiers YAML en utilisant des outils tels que diff virtuellement impossible si vous utilisez des mappages et de charger/modifier/vider les fichiers, ce qui rend la vérification de ces fichiers dans les systèmes de contrôle de révision induite par des modifications sémantiquement identiques. , mais pas syntaxiquement.

Je entrepris d'améliorer PyYAML pour d'autres raisons (compatibilité YAML 1.2 à la place de l'ancien 1.1 spec, préservation des commentaires, des corrections de bugs), mais ruamel.yaml conserve également la commande comme des applications si vous utilisez son round_trip_dump:

import ruamel.yaml 
from ruamel.yaml.comments import CommentedMap as OrderedDict 

a = OrderedDict() 
a['name'] = 'hello' 
a['msgs'] = ['hello', 'world'] 

with open("b.yaml", 'w') as stream: 
    ruamel.yaml.round_trip_dump(a, stream, indent=5, block_seq_indent=3) 

qui vous donne un fichier b.yaml avec le contenu:

name : hello 
msgs: 
    - hello 
    - world 

qui est exactement ce que vous attendiez.

S'il vous plaît noter que j'ai passé dans le flux de la round_trip_dump, si vous utilisez PyYAML vous devriez le faire aussi bien, car il est plus efficace.
Vous devez utiliser le CommentedMap, qui est juste une enveloppe mince autour OrderedDict/ordereddict qui permet la conservation des commentaires etc.
Par défaut indent est 2 et block_seq_indent est 0.

Si vous chargez votre fichier en utilisant round_trip_dump, vous obtiendrez à nouveau un CommentedMap dans lequel l'ordre des clés sera comme prévu.