我有代码打印出一个像YAML一样的字典:
import yaml
yaml.dump(
{
"Properties":
{
"ImageId": "!Ref AParameter"
}
},
new_template,
default_flow_style=False
)
这会创建:
Properties:
ImageId: '!Ref AParameter'
注意ImageId的值是如何在引号内?我想打印没有引号。我如何使用PyYAML做到这一点?
答案 0 :(得分:1)
!
具有特殊含义,因为它用于引入an explicit tag,因此不能出现在普通(未引用)样式标量的开头。特别是YAML 1.2规范的rule 126表示这样一个普通标量的第一个字符不能是c-indicator
,这就是!
。
这样的标量必须引用(单个或双重)PyYAML自动执行,或者以文字或折叠方式放置。
您可以将没有引号的有效YAML转储到文字块样式标量:
Properties:
ImageId: |
!Ref AParameter
如果没有支持性编程,PyYAML就无法做到这一点。您可以使用ruamel.yaml执行此操作(免责声明:我是该程序包的作者),将值设为PreservedScalarString
实例:ruamel.yaml.scalarstring.PreservedScalarString("!Ref AParameter")
您当然可以使用!Ref
标记定义转储的类,但标记上下文会强制标量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