如何从嵌套字典生成不含引号的Jinja2变量YAML模板?
问题
我有如下嵌套字典:
{'n11' : {'n12a': {'n13a' : '{{n11_n12a_n13a}}' , 'n13b' : '{{n11_n12a_n13b}}'}, 'n12b': {'n13c' : {'n14a': '{{n11_n12b_n13c_n14a}}'} } }, 'n21': {'n22a' : '{{n21_n22a}}' } }
我希望基于它生成这样的YAML模板:
n11 : n12a: n13a: {{n11_n12a_n13a}} n13b: {{n11_n12a_n13b}} n12b: n13c: n14a: {{n11_n12b_n13c_n14a}} n21 : n22a: {{n21_n22a}}
但直接用以下代码导出时:
import yaml ff = open('./dictionary_to_template.yaml', 'w+') yaml.dump(dictionary, ff, allow_unicode=True)
生成的YAML里Jinja2变量会带引号:
n11 : n12a: n13a: "{{n11_n12a_n13a}}" n13b: "{{n11_n12a_n13b}}" n12b: n13c: n14a: "{{n11_n12b_n13c_n14a}}" n21 : n22a: "{{n21_n22a}}"
请问怎么生成YAML文件时去掉这些引号,让它成为正确的Jinja2变量?
附生成字典的代码:
d = {'n11' : {'n12a': {'n13a' : '{{n11_n12a_n13a}}' , 'n13b' : '{{n11_n12a_n13b}}'}, 'n12b': {'n13c' : {'n14a': '{{n11_n12b_n13c_n14a}}' }}, 'n21': {'n22a' : '{{n21_n22a}}' }}}
解决方案
PyYAML会把包含{{}}的字符串识别为需要引号包裹的特殊格式,要去掉引号,你可以自定义一个YAML代表器,告诉PyYAML直接输出原始字符串,不添加引号。
具体实现步骤
- 定义一个自定义字符串类,用来标记需要原样输出的Jinja2变量;
- 为这个类注册专属的YAML代表器,指定输出时不添加引号;
- 将原字典中的普通Jinja变量字符串替换为自定义类的实例;
- 用修改后的字典生成YAML文件。
完整代码示例
import yaml # 定义自定义字符串类,用于标记Jinja2变量 class JinjaStr(str): pass # 自定义代表器,直接输出字符串内容,不添加引号 def jinja_str_representer(dumper, data): return dumper.represent_scalar('tag:yaml.org,2002:str', data, style='') # 注册自定义代表器 yaml.add_representer(JinjaStr, jinja_str_representer) # 构建带自定义类型的字典 d = { 'n11': { 'n12a': { 'n13a': JinjaStr('{{n11_n12a_n13a}}'), 'n13b': JinjaStr('{{n11_n12a_n13b}}') }, 'n12b': { 'n13c': { 'n14a': JinjaStr('{{n11_n12b_n13c_n14a}}') } } }, 'n21': { 'n22a': JinjaStr('{{n21_n22a}}') } } # 写入YAML文件 with open('./dictionary_to_template.yaml', 'w+', encoding='utf-8') as ff: yaml.dump(d, ff, allow_unicode=True, default_flow_style=False)
补充说明
如果你不想修改原字典的类型,也可以直接修改PyYAML对普通字符串的处理逻辑,但这种方式可能影响其他正常字符串的输出格式,因此更推荐用自定义类型的方式,精准控制需要原样输出的内容。
内容的提问来源于stack exchange,提问作者Kspr
相关产品推荐
相关产品推荐

