您的困难是由于多个级别的假设不正确,并且根据您的 YAML 解析器,可能无法透明地解决。
在 Python 的 dict 中,键是无序的(至少对于 Python 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
它将按照在源中指定的顺序打印键。
第二个问题是,即使 Python dict 有一些恰好是您想要的键顺序,YAML 规范确实明确表示映射是无序的,这就是例如PyYAML 实现了 Python dict 到 YAML 映射的转储(反之亦然)。
此外,如果您转储一个 ordereddict 或 OrderedDict,您通常不会得到您想要的纯 YAML 映射,而是一些标记的 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'] 也是如此,但在它们下面是更智能的构造,可以保留顺序、cmets、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 数据结构的速度更快。