使用 yaml.dump 时如何去掉字符串中的引号
How to get rid of quotes in strings when using yaml.dump
我正在尝试使用 ruamel.yaml 从有序字典生成 cloudformation YAML 模板。
我需要在一些字符串前加上“!Sub
”前缀,这是一个 cloudtemplate 函数引用,它不会与其余字符串一起用引号引起来,例如:
Type: AWS::Glue::Job
Properties:
Role2: !Sub 'arn:aws:iam::${AWS::AccountId}:role/${GlueServiceRole}'
我开始的测试代码如下所示:
from ruamel import yaml
from collections import OrderedDict
def ordered_dict_presenter(dumper, data):
return dumper.represent_dict(data.items())
test = OrderedDict(
{
"Type": "AWS::Glue::Job",
"Properties": {
"Name": "test_job",
"Role": "!Sub arn:aws:iam::${AWS::AccountId}:role/${GlueServiceRole}",
"Role2": "Sub arn:aws:iam::${AWS::AccountId}:role/${GlueServiceRole}",
},
}
)
yaml.add_representer(OrderedDict, ordered_dict_presenter)
print(yaml.dump(test, default_style=None, default_flow_style=False))
它输出这个 yaml:
Type: AWS::Glue::Job
Properties:
Name: test_job
Role: '!Sub arn:aws:iam::${AWS::AccountId}:role/${GlueServiceRole}'
Role2: Sub arn:aws:iam::${AWS::AccountId}:role/${GlueServiceRole}
似乎当字符串以非字母字符开头时,它会被自动引用。
我尝试了自定义代表来摆脱引号,但到目前为止没有任何运气。我怎样才能输出这个?
首先你真的不应该再使用旧的 API 了,有一个新的,它允许更多的控制
关于你几年来所做的事情。
其次,你不能把一些看起来像标签的东西放在字符串中,然后
没有得到报价,在加载过程中会像标签一样加载,你可能想要
那个,但是那会产生无限数量的字符串(所有以
!
) 在 YAML 中不可表示。
如果您不知道从哪里开始,可以尝试往返(加载然后转储)您需要的结果:
import sys
import ruamel.yaml
yaml_str = """\
Type: AWS::Glue::Job
Properties:
Role2: !Sub arn:aws:iam::${AWS::AccountId}:role/${GlueServiceRole}
"""
yaml = ruamel.yaml.YAML()
yaml.preserve_quotes = True
data = yaml.load(yaml_str)
yaml.dump(data, sys.stdout)
这给出:
Type: AWS::Glue::Job
Properties:
Role2: !Sub arn:aws:iam::${AWS::AccountId}:role/${GlueServiceRole}
这确认 ruamel.yaml 可以创建输出。现在你只需要从头开始。为此你可以
检查 data
尤其是 data['Properties']['Role2']
(如果事情不经常往返但不是必需的,意味着
你无法生成你想要的东西,但在这种情况下找出如何去做可能会更难)。
print(type(data['Properties']['Role2']))
这会打印:
Type: AWS::Glue::Job
Properties:
Role2: !Sub arn:aws:iam::${AWS::AccountId}:role/${GlueServiceRole}
<class 'ruamel.yaml.comments.TaggedScalar'>
现在你只需要了解 TaggedScalar 的工作原理(源代码在 comments.py
):
import sys
import ruamel.yaml
data = {}
data['Properties'] = props = {}
props['Role2'] = ruamel.yaml.comments.TaggedScalar('arn:aws:iam::${AWS::AccountId}:role/${GlueServiceRole}', style=None, tag='!Sub')
yaml = ruamel.yaml.YAML()
yaml.preserve_quotes = True
yaml.dump(data, sys.stdout)
给予:
Properties:
Role2: !Sub arn:aws:iam::${AWS::AccountId}:role/${GlueServiceRole}
或者如果您确实想要引号,您可以指定 style="'"
或 style='"'
。
我正在尝试使用 ruamel.yaml 从有序字典生成 cloudformation YAML 模板。
我需要在一些字符串前加上“!Sub
”前缀,这是一个 cloudtemplate 函数引用,它不会与其余字符串一起用引号引起来,例如:
Type: AWS::Glue::Job
Properties:
Role2: !Sub 'arn:aws:iam::${AWS::AccountId}:role/${GlueServiceRole}'
我开始的测试代码如下所示:
from ruamel import yaml
from collections import OrderedDict
def ordered_dict_presenter(dumper, data):
return dumper.represent_dict(data.items())
test = OrderedDict(
{
"Type": "AWS::Glue::Job",
"Properties": {
"Name": "test_job",
"Role": "!Sub arn:aws:iam::${AWS::AccountId}:role/${GlueServiceRole}",
"Role2": "Sub arn:aws:iam::${AWS::AccountId}:role/${GlueServiceRole}",
},
}
)
yaml.add_representer(OrderedDict, ordered_dict_presenter)
print(yaml.dump(test, default_style=None, default_flow_style=False))
它输出这个 yaml:
Type: AWS::Glue::Job
Properties:
Name: test_job
Role: '!Sub arn:aws:iam::${AWS::AccountId}:role/${GlueServiceRole}'
Role2: Sub arn:aws:iam::${AWS::AccountId}:role/${GlueServiceRole}
似乎当字符串以非字母字符开头时,它会被自动引用。 我尝试了自定义代表来摆脱引号,但到目前为止没有任何运气。我怎样才能输出这个?
首先你真的不应该再使用旧的 API 了,有一个新的,它允许更多的控制 关于你几年来所做的事情。
其次,你不能把一些看起来像标签的东西放在字符串中,然后
没有得到报价,在加载过程中会像标签一样加载,你可能想要
那个,但是那会产生无限数量的字符串(所有以
!
) 在 YAML 中不可表示。
如果您不知道从哪里开始,可以尝试往返(加载然后转储)您需要的结果:
import sys
import ruamel.yaml
yaml_str = """\
Type: AWS::Glue::Job
Properties:
Role2: !Sub arn:aws:iam::${AWS::AccountId}:role/${GlueServiceRole}
"""
yaml = ruamel.yaml.YAML()
yaml.preserve_quotes = True
data = yaml.load(yaml_str)
yaml.dump(data, sys.stdout)
这给出:
Type: AWS::Glue::Job
Properties:
Role2: !Sub arn:aws:iam::${AWS::AccountId}:role/${GlueServiceRole}
这确认 ruamel.yaml 可以创建输出。现在你只需要从头开始。为此你可以
检查 data
尤其是 data['Properties']['Role2']
(如果事情不经常往返但不是必需的,意味着
你无法生成你想要的东西,但在这种情况下找出如何去做可能会更难)。
print(type(data['Properties']['Role2']))
这会打印:
Type: AWS::Glue::Job
Properties:
Role2: !Sub arn:aws:iam::${AWS::AccountId}:role/${GlueServiceRole}
<class 'ruamel.yaml.comments.TaggedScalar'>
现在你只需要了解 TaggedScalar 的工作原理(源代码在 comments.py
):
import sys
import ruamel.yaml
data = {}
data['Properties'] = props = {}
props['Role2'] = ruamel.yaml.comments.TaggedScalar('arn:aws:iam::${AWS::AccountId}:role/${GlueServiceRole}', style=None, tag='!Sub')
yaml = ruamel.yaml.YAML()
yaml.preserve_quotes = True
yaml.dump(data, sys.stdout)
给予:
Properties:
Role2: !Sub arn:aws:iam::${AWS::AccountId}:role/${GlueServiceRole}
或者如果您确实想要引号,您可以指定 style="'"
或 style='"'
。