本文介绍了YAML错误:无法确定标记的构造函数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这非常类似于 questions/44786412 ,但我的似乎是由YAML safe_load()触发的.我正在使用Ruamel的 YamlReader 将一堆CloudFormation片段粘合在一起,成为一个合并的模板.爆炸符号是否只是不正确的YAML?

This is very similar to questions/44786412 but mine appears to be triggered by YAML safe_load(). I'm using Ruamel's library and YamlReader to glue a bunch of CloudFormation pieces together into a single, merged template. Is bang-notation just not proper YAML?

Outputs:
  Vpc:
    Value: !Ref vpc
    Export:
      Name: !Sub "${AWS::StackName}-Vpc"

这些没问题

Outputs:
  Vpc:
    Value:
      Ref: vpc
    Export:
      Name:
        Fn::Sub: "${AWS::StackName}-Vpc"

Resources:
  vpc:
    Type: AWS::EC2::VPC
    Properties:
      CidrBlock:
        Fn::FindInMap: [ CidrBlock, !Ref "AWS::Region", Vpc ]


第2部分;如何获得load()来不让'Fn :: Select:'的权利独处.


Part 2; how to get load() to leave what's right of the 'Fn::Select:' alone.

  FromPort: 
    Fn::Select: [ 0, Fn::FindInMap: [ Service, https, Ports ] ]

被转换为此,现在CF不喜欢.

gets converted to this, that now CF doesn't like.

  FromPort:
    Fn::Select: [0, {Fn::FindInMap: [Service, https, Ports]}]

如果我完全展开该语句,则没有问题.我想速记就是有问题的.

If I unroll the statement fully then no problems. I guess the shorthand is just problematic.

  FromPort:
    Fn::Select:
    - 0
    - Fn::FindInMap: [Service, ssh, Ports]

推荐答案

您的爆炸符号"是正确的YAML,通常称为 tag .如果要与 safe_load()一起使用,则必须提供!Ref !Sub 标记的构造函数,例如使用:

Your "bang notation" is proper YAML, normally this is called a tag. If you want to use the safe_load() with those you'll have to provide constructors for the !Ref and !Sub tags, e.g. using:

ruamel.yaml.add_constructor(u'!Ref', your_ref_constructor, constructor=ruamel.yaml.SafeConstructor)

对于这两个标记,您应该期望在其中处理标量值.而不是更常见的映射.

where for both tags you should expect to handle scalars a value. and not the more common mapping.

我建议您使用 RoundTripLoader 而不是 SafeLoader ,这样也会保留顺序,注释等. RoundTripLoader SafeLoader 的子类.

I recommend you use the RoundTripLoader instead of the SafeLoader, that will preserve order, comments, etc. as well. The RoundTripLoader is a subclass of the SafeLoader.

如果您使用的是支持往返标量的ruamel.yaml> = 0.15.33,则可以这样做(使用新的ruamel.yaml API):

If you are using ruamel.yaml>=0.15.33, which supports round-tripping scalars, you can do (using the new ruamel.yaml API):

import sys
from ruamel.yaml import YAML

yaml = YAML()
yaml.preserve_quotes = True

data = yaml.load("""\
Outputs:
  Vpc:
    Value: !Ref: vpc    # first tag
    Export:
      Name: !Sub "${AWS::StackName}-Vpc"  # second tag
""")

yaml.dump(data, sys.stdout)

获取:

Outputs:
  Vpc:
    Value: !Ref: vpc    # first tag
    Export:
      Name: !Sub "${AWS::StackName}-Vpc"  # second tag

在较旧的0.15.X版本中,您必须自己指定标量对象的类.如果您有很多对象,这会很麻烦,但是它允许其他功能:

In older 0.15.X versions, you'll have to specify the classes for the scalar objects yourself. This is cumbersome, if you have many objects, but allows for additional functionality:

import sys
from ruamel.yaml import YAML


class Ref:
    yaml_tag = u'!Ref:'

    def __init__(self, value, style=None):
        self.value = value
        self.style = style

    @classmethod
    def to_yaml(cls, representer, node):
        return representer.represent_scalar(cls.yaml_tag,
                                            u'{.value}'.format(node), node.style)

    @classmethod
    def from_yaml(cls, constructor, node):
        return cls(node.value, node.style)

    def __iadd__(self, v):
        self.value += str(v)
        return self

class Sub:
    yaml_tag = u'!Sub'
    def __init__(self, value, style=None):
        self.value = value
        self.style = style

    @classmethod
    def to_yaml(cls, representer, node):
        return representer.represent_scalar(cls.yaml_tag,
                                            u'{.value}'.format(node), node.style)

    @classmethod
    def from_yaml(cls, constructor, node):
        return cls(node.value, node.style)


yaml = YAML(typ='rt')
yaml.register_class(Ref)
yaml.register_class(Sub)

data = yaml.load("""\
Outputs:
  Vpc:
    Value: !Ref: vpc    # first tag
    Export:
      Name: !Sub "${AWS::StackName}-Vpc"  # second tag
""")

data['Outputs']['Vpc']['Value'] += '123'

yaml.dump(data, sys.stdout)

给出:

Outputs:
  Vpc:
    Value: !Ref: vpc123 # first tag
    Export:
      Name: !Sub "${AWS::StackName}-Vpc"  # second tag

这篇关于YAML错误:无法确定标记的构造函数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

10-30 18:38