Dumping a dictionary into a YAML file while maintaining order

I am trying to upload a dictionary to a YAML file. The problem is that the program that imports the YAML file needs keywords in a specific order. This order is not in alphabetical order.

import yaml
import os 

baseFile = 'myfile.dat'
lyml = [{'BaseFile': baseFile}]
lyml.append({'Environment':{'WaterDepth':0.,'WaveDirection':0.,'WaveGamma':0.,'WaveAlpha':0.}})

CaseName = 'OrderedDict.yml'
CaseDir = r'C:\Users\BTO\Documents\Projects\Mooring code testen'
CaseFile = os.path.join(CaseDir, CaseName)
with open(CaseFile, 'w') as f:
    yaml.dump(lyml, f, default_flow_style=False)

This creates a * .yml file that is formatted as follows:

- BaseFile: myfile.dat
- Environment:
    WaterDepth: 0.0
    WaveAlpha: 0.0
    WaveDirection: 0.0
    WaveGamma: 0.0

But I want the order to be preserved:

- BaseFile: myfile.dat
- Environment:
    WaterDepth: 0.0
    WaveDirection: 0.0
    WaveGamma: 0.0
    WaveAlpha: 0.0

Is it possible?

+7
source share
5 answers

Use dicteddict instead of dict. Run the installation code below at the beginning. Now yaml.dump, I have to keep order. More here and here

def setup_yaml():
  """ /questions/400588/controlling-yaml-serialization-order-in-python/1815106#1815106 """
  represent_dict_order = lambda self, data:  self.represent_mapping('tag:yaml.org,2002:map', data.items())
  yaml.add_representer(OrderedDict, represent_dict_order)    
setup_yaml()

Example: https://pastebin.com/raw.php?i=NpcT6Yc4

+26

PyYAML representer, YAML node.

yaml.YAMLObject , YAML node , YAML node.

:

def represent_dictionary_order(self, dict_data):
    return self.represent_mapping('tag:yaml.org,2002:map', dict_data.items())

def setup_yaml():
    yaml.add_representer(OrderedDict, represent_dictionary_order)

setup_yaml()

OrderedDict yaml.dump():

import yaml
from collections import OrderedDict

def represent_dictionary_order(self, dict_data):
    return self.represent_mapping('tag:yaml.org,2002:map', dict_data.items())

def setup_yaml():
    yaml.add_representer(OrderedDict, represent_dictionary_order)

setup_yaml()    

dic = OrderedDict()

dic['a'] = 1
dic['b'] = 2
dic['c'] = 3

print(yaml.dump(dic))
# {a: 1, b: 2, c: 3}
+4

- , , YAML, .

Python dict ( , Python < 3.6). , dict, :

d = {'WaterDepth':0.,'WaveDirection':0.,'WaveGamma':0.,'WaveAlpha':0.}
for key in d:
    print key

:

WaterDepth
WaveGamma
WaveAlpha
WaveDirection

, , collection.OrderedDict( ruamel.ordereddict, C ), , :

from ruamel.ordereddict import ordereddict
# from collections import OrderedDict as ordereddict  # < this will work as well
d = ordereddict([('WaterDepth', 0.), ('WaveDirection', 0.), ('WaveGamma', 0.), ('WaveAlpha', 0.)])
for key in d:
    print key

, .

, Python , , , YAML , , , . PyYAML Python dict YAML ( ). , orderdict OrderedDict, , , -, , , , YAML.

, , - , , , /, ruamel.yaml, :

import sys
import ruamel.yaml as yaml

yaml_str = """\
- BaseFile: myfile.dat
- Environment:
    WaterDepth: 0.0
    WaveDirection: 0.0
    WaveGamma: 0.0
    WaveAlpha: 0.0
"""

data = yaml.load(yaml_str, Loader=yaml.RoundTripLoader)
print(data)
yaml.dump(data, sys.stdout, Dumper=yaml.RoundTripDumper)

. data dict ( `data ['Environment'], , , , YAML ..). , , (/ -), , :

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

baseFile = 'myfile.dat'
lyml = [{'BaseFile': baseFile}]
lyml.append({'Environment': CommentedMap([('WaterDepth', 0.), ('WaveDirection', 0.), ('WaveGamma', 0.), ('WaveAlpha', 0.)])})
yaml.dump(data, sys.stdout, Dumper=yaml.RoundTripDumper)

, . , , YAML, lyml.

+1

3 - yaml.dump kwarg sort_keys, True. False, :

with open(CaseFile, 'w') as f:
    yaml.dump(lyml, f, default_flow_style=False, sort_keys=False)
0

@Eric . , .

, , :)

0

Source: https://habr.com/ru/post/1599460/


All Articles