Python 3.x 在保留顺序的同时将字典转储到YAML文件

Python 3.x 在保留顺序的同时将字典转储到YAML文件,python-3.x,dictionary,yaml,Python 3.x,Dictionary,Yaml,我一直在尝试将字典转储到YAML文件中。问题是导入YAML文件的程序需要按特定顺序输入关键字。此顺序不是按字母顺序排列的 import yaml import os baseFile = 'myfile.dat' lyml = [{'BaseFile': baseFile}] lyml.append({'Environment':{'WaterDepth':0.,'WaveDirection':0.,'WaveGamma':0.,'WaveAlpha':0.}}) CaseName = '

我一直在尝试将字典转储到YAML文件中。问题是导入YAML文件的程序需要按特定顺序输入关键字。此顺序不是按字母顺序排列的

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)
这将生成一个*.yml文件,其格式如下:

- BaseFile: myfile.dat
- Environment:
    WaterDepth: 0.0
    WaveAlpha: 0.0
    WaveDirection: 0.0
    WaveGamma: 0.0
但我想要的是秩序得以维持:

- BaseFile: myfile.dat
- Environment:
    WaterDepth: 0.0
    WaveDirection: 0.0
    WaveGamma: 0.0
    WaveAlpha: 0.0
这可能吗

使用而不是dict。在开始时运行以下设置代码。现在,yaml.dump应保留订单。更多详情及


示例:

您的困难是由于在多个级别上的假设是不正确的,并且根据您的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
如果要对键进行排序,可以使用collections.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
这会准确地给出输出结果<代码>数据作为一个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数据结构的速度要快一些。

支持
representer
将类实例序列化到YAML节点

yaml.YAMLObject使用元类魔术注册构造函数(将yaml节点转换为类实例)和重新输入(将类实例序列化为yaml节点)

在代码上方添加以下行:

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()中保留订单


3年后-yaml.dump有一个sort_keys kwarg,默认设置为True。将其设置为False以不重新排序:

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

不知何故,我无法在代码块中编写代码。我的观点是,使用上述解决方案,无法获得所需的结构?因为OrderedDict(['Environment',(WaterDepth,0),(WaveDirection,0,(WaveGamma,0),(WaveAlpha,0)]不正确。有什么建议吗?简单明了!
TypeError:dump\u all()得到了一个意外的关键字参数“sort\u keys”
sort\u keys=False必须是默认值,只是浪费了4个小时~___~
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()
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}
with open(CaseFile, 'w') as f:
    yaml.dump(lyml, f, default_flow_style=False, sort_keys=False)