如何打印出来!在皮亚尔?

How to print out the ! in pyaml?

我有代码可以像 YAML 一样打印出字典:

    import yaml
    yaml.dump(
        {
        "Properties":
             {
                 "ImageId": "!Ref AParameter"
             }
        },
        new_template,
        default_flow_style=False
    )

这将创建:

Properties:
  ImageId: '!Ref AParameter'

注意引号内的 ImageId 值了吗?我想打印不带引号。我如何使用 PyYAML 做到这一点?

!有特殊的含义,用来介绍an explicit tag, and therefore cannot appear at the beginning of a plain (unquoted) style scalar. Specifically rule 126 of the YAML 1.2 specification indicates that the first character of such a plain scalar cannot be a c-indicator,也就是!

这样的标量必须被 PyYAML 自动引用(单引号或双引号),或者以文字或折叠块样式放置。

您可以将不带引号的有效 YAML 转储为文字块样式标量:

Properties:
  ImageId: |
    !Ref AParameter

如果没有支持性的编程,PyYAML 无法做到这一点。您可以使用 ruamel.yaml 通过将值设为 PreservedScalarString 实例来执行此操作(免责声明:我是该包的作者):ruamel.yaml.scalarstring.PreservedScalarString("!Ref AParameter")

您当然可以使用 !Ref 标签定义转储的 class,但标签上下文将强制在标量 AParameter:

周围加上引号
import sys
import yaml

class Ref(str):
    @staticmethod
    def yaml_dumper(dumper, data):
        return dumper.represent_scalar('!Ref', u'{}'.format(data), style=None)

yaml.add_representer(Ref, Ref.yaml_dumper)


yaml.dump(
    {
        "Properties":
        {
            "ImageId": Ref("AParameter"),
        }
    },
    sys.stdout,
    default_flow_style=False,
)

给出:

Properties:
  ImageId: !Ref 'AParameter'

尽管使用适当的构造函数 加载 !Ref Aparameter 可能的(即为了安全起见,这里只是添加引号)。

如果您还想隐藏这些引号,您可以例如使用 ruamel.yaml,通过为您的节点定义特殊样式 'x' 并为此提供发射处理:

from ruamel import yaml

class Ref(str):
    @staticmethod
    def yaml_dumper(dumper, data):
        return dumper.represent_scalar('!Ref', u'{}'.format(data), style='x')

    @staticmethod
    def yaml_constructor(loader, node):
        value = loader.construct_scalar(node)
        return Ref(value)

yaml.add_representer(Ref, Ref.yaml_dumper)
yaml.add_constructor('!Ref', Ref.yaml_constructor,
                     constructor=yaml.constructor.SafeConstructor)

def choose_scalar_style(self):
    if self.event.style == 'x':
        return ''
    return self.org_choose_scalar_style()

yaml.emitter.Emitter.org_choose_scalar_style = yaml.emitter.Emitter.choose_scalar_style
yaml.emitter.Emitter.choose_scalar_style = choose_scalar_style

data =  {
    "Properties":
    {
        "ImageId": Ref("AParameter"),
    }
}

ys = yaml.dump(data, default_flow_style=False)

print(ys)
data_out = yaml.safe_load(ys)
assert data_out == data

以上不会在断言上引发错误,因此数据往返和打印输出 AFAICT 正是您想要的:

Properties:
  ImageId: !Ref AParameter