使用alias和YAMLORDEREDDITCTLOADER加载程序时未保留YAML映射顺序

使用alias和YAMLORDEREDDITCTLOADER加载程序时未保留YAML映射顺序,yaml,python-3.6,pyyaml,ordereddictionary,Yaml,Python 3.6,Pyyaml,Ordereddictionary,我想将YAML文件作为OrderedDict加载到Python中。我正在使用YamLorderedditLoader来保持顺序 但是,我注意到别名对象在输出的OrderedDict中放置得“太早” 在读入Python时,我如何保持这种映射的顺序,理想情况下是作为orderedict?是否可以在不编写自定义解析的情况下实现此结果 注意事项: 我并不特别关心所使用的方法,只要最终结果是一样的 使用序列而不是映射是有问题的,因为它们会导致嵌套输出,而且我不能简单地将所有内容展平(一些嵌套是合适的)

我想将YAML文件作为
OrderedDict
加载到Python中。我正在使用YamLorderedditLoader来保持顺序

但是,我注意到别名对象在输出的OrderedDict中放置得“太早”

在读入Python时,我如何保持这种映射的顺序,理想情况下是作为
orderedict
?是否可以在不编写自定义解析的情况下实现此结果

注意事项:

  • 我并不特别关心所使用的方法,只要最终结果是一样的
  • 使用序列而不是映射是有问题的,因为它们会导致嵌套输出,而且我不能简单地将所有内容展平(一些嵌套是合适的)
  • 当我尝试只使用
    !!omap
    ,我似乎无法将别名映射(
    d1.dt
    )合并到
    d2
    映射中
  • 如果我不使用这个加载程序或
    ,那么我使用的是Python 3.6!!omap
    订单未保留(显然与此处顶部的“更新”相反:)
导入yaml
导入yamlordereddictloader
yaml_文件=”“
d1:
身份证件:
nm1:val1
dt:&dt
nm2:val2
nm3:val3
d2:#除nm4、nm2、nm3外
nm4:val4
是否可以在不编写自定义解析的情况下实现此结果

是的。您需要覆盖来自
SafeConstructor
的方法
flant\u mapping
。下面是一个基本的工作示例:

导入yaml
导入yamlordereddictloader
从yaml.constructor导入*
从yaml.reader导入*
从yaml.parser导入*
从yaml.resolver导入*
从yaml.composer导入*
从yaml.scanner导入*
从yaml.nodes导入*
类MyLoader(YamLordReditLoader.Loader):
定义初始化(自,流):
YamLorderAddictloader.Loader.\uuuu init\uuuu(self,stream)
#从这里开始,重新设计以维持秩序:
# https://github.com/yaml/pyyaml/blob/5.3.1/lib/yaml/constructor.py#L207
def展平映射(自身、节点):
合并=[]
def merge_from(节点):
如果不是isinstance(节点,映射节点):
引发yaml.ConstructorError(“在构造映射时”,
node.start_标记,“预期的合并映射,但找到%s”%
node.id,node.start(标记)
自展平映射(节点)
merged.extend(node.value)
对于范围内的索引(len(node.value)):
键节点,值节点=节点。值[索引]
如果key_node.tag==u'tag:yaml.org,2002:merge':
如果isinstance(值\节点,序列节点):
对于value_node.value中的子节点:
合并来自(子节点)
其他:
合并来自(值节点)
其他:
如果key_node.tag==u'tag:yaml.org,2002:value':
key_node.tag=u'tag:yaml.org,2002:str'
合并的.append((键节点,值节点))
node.value=合并
yaml_文件=”“
d1:
身份证件:
nm1:val1
dt:&dt
nm2:val2
nm3:val3
d2:#除nm4、nm2、nm3外
nm4:val4
import yaml
import yamlordereddictloader

yaml_file = """
d1:
  id:
    nm1: val1
  dt: &dt
    nm2: val2
    nm3: val3

d2: # expect nm4, nm2, nm3
  nm4: val4
  <<: *dt
"""

out = yaml.load(yaml_file, Loader=yamlordereddictloader.Loader)
keys = [x for x in out['d2']]
print(keys) # ['nm2', 'nm3', 'nm4']
assert keys==['nm4', 'nm2', 'nm3'], "order from YAML file is not preserved, aliased keys placed too early"