Python 使用 jinja2 为嵌套结构创建动态 YAML 文件
Python creating dynamic YAML file using jinja2 for nested structures
我需要创建一个基于简单 YAML 的 YAML 文件,该文件需要根据开发人员提供的属性进行更新并包含以下 YAML 结构:
- switch: null
title: switch
case:
- condition: (parameter1==='Parameter1_value1')
execute:
- switch:
case:
- condition: $(parameter2) == "Parameter2_value1"
execute:
- invoke:
parameter3:
parameter3_value1: null
- condition: $(parameter2) == "Parameter2_value2"
execute:
- invoke:
parameter3:
parameter3_value2: null
- condition: (parameter1==='Parameter1_value2')
execute:
- switch:
case:
- condition: $(parameter2) == "Parameter2_value1"
execute:
- invoke:
parameter3:
parameter3_value1: null
- condition: $(parameter2) == "Parameter2_value2"
execute:
- invoke:
parameter3:
parameter3_value2: null
parameter1
和 parameter2
都可以有多个值,因此我需要根据收到的值动态填充结构。
我尝试执行以下操作:
- 导入以下内容
import ruamel.yaml
from jinja2 import Template
- 加载基本文件-
yaml = ruamel.yaml.YAML()
data_src = yaml.load(file_name)
同时从另一个 JSON 文件接收值,一旦我有了数据,我就使用 Jinja 创建了以下内容:
parameter2_data_tmpl = Template(""" - condition: $(parameter2) == "{{ parameter2_value }}"
execute:
- invoke:
parameter3: {{ parameter3_value }}
""");
parameter2_data = parameter2_data_tmpl.render(parameter2_value = parameter2_value, parameter3_value = parameter3_value)
这就像一个魅力,当我打印它时 - 它看起来很棒。但后来我尝试将新的 YAML 片段添加到我的结构中,方法是首先将其添加到相关数组(使用 append 方法),然后将该数组分配给原始 YAML 结构中的相关元素。
但是当我将它添加到数组时,它以不同的格式添加:
case: [' - condition: parameter2 == \"\
parameter2_value\"\n execute:\n -\
parameter3: parameter3_value\n \
就像 jinja2 正确地创建了它,但不是 YAML 语法。
为什么这不起作用?除了动态创建这些代码之外,还有其他方法吗?
渲染的结果是一个字符串:
from jinja2 import Template
parameter2_data_tmpl = Template(""" - condition: $(parameter2) == "{{ parameter2_value }}"
execute:
- invoke:
parameter3: {{ parameter3_value }}
""");
parameter2_value = 'parameter2_value'
parameter3_value = 'parameter3_value'
parameter2_data = parameter2_data_tmpl.render(parameter2_value = parameter2_value, parameter3_value = parameter3_value)
print(type(parameter2_data))
这给出:
<class 'str'>
当您将该字符串添加到您使用 ruamel.yaml
加载的数据结构中的某处时,您
获取带引号的标量。
你想做的是添加一个数据结构,但是你不能从
模板,因为渲染的输出是无效的 YAML。
你可以不渲染直接创建数据结构,如果你不想
为此,您应该更改模板,以便它生成有效的 YAML 输入,加载
然后将该数据结构插入 data_src
的适当位置
(从你不完整的程序中不清楚):
import sys
import ruamel.yaml
from jinja2 import Template
parameter2_data_tmpl = Template("""\
- condition: $(parameter2) == "{{ parameter2_value }}"
execute:
- invoke:
parameter3: {{ parameter3_value }}
""");
parameter2_value = 'parameter2_value'
parameter3_value = 'parameter3_value'
parameter2_data = parameter2_data_tmpl.render(parameter2_value = parameter2_value, parameter3_value = parameter3_value)
yaml = ruamel.yaml.YAML()
yaml.indent(sequence=4, offset=2)
new_data = yaml.load(parameter2_data)
data = yaml.load("""\
case: some value to overwrite
""")
data['case'] = new_data
yaml.dump(data, sys.stdout)
给出:
case:
- condition: $(parameter2) == "parameter2_value"
execute:
- invoke:
parameter3: parameter3_value
请注意还有一个插件ruamel.yaml.jinja2
允许你加载
生成 YAML 输出和修改值的未呈现的 Jinja2 模板。
我需要创建一个基于简单 YAML 的 YAML 文件,该文件需要根据开发人员提供的属性进行更新并包含以下 YAML 结构:
- switch: null
title: switch
case:
- condition: (parameter1==='Parameter1_value1')
execute:
- switch:
case:
- condition: $(parameter2) == "Parameter2_value1"
execute:
- invoke:
parameter3:
parameter3_value1: null
- condition: $(parameter2) == "Parameter2_value2"
execute:
- invoke:
parameter3:
parameter3_value2: null
- condition: (parameter1==='Parameter1_value2')
execute:
- switch:
case:
- condition: $(parameter2) == "Parameter2_value1"
execute:
- invoke:
parameter3:
parameter3_value1: null
- condition: $(parameter2) == "Parameter2_value2"
execute:
- invoke:
parameter3:
parameter3_value2: null
parameter1
和 parameter2
都可以有多个值,因此我需要根据收到的值动态填充结构。
我尝试执行以下操作:
- 导入以下内容
import ruamel.yaml
from jinja2 import Template
- 加载基本文件-
yaml = ruamel.yaml.YAML()
data_src = yaml.load(file_name)
同时从另一个 JSON 文件接收值,一旦我有了数据,我就使用 Jinja 创建了以下内容:
parameter2_data_tmpl = Template(""" - condition: $(parameter2) == "{{ parameter2_value }}"
execute:
- invoke:
parameter3: {{ parameter3_value }}
""");
parameter2_data = parameter2_data_tmpl.render(parameter2_value = parameter2_value, parameter3_value = parameter3_value)
这就像一个魅力,当我打印它时 - 它看起来很棒。但后来我尝试将新的 YAML 片段添加到我的结构中,方法是首先将其添加到相关数组(使用 append 方法),然后将该数组分配给原始 YAML 结构中的相关元素。
但是当我将它添加到数组时,它以不同的格式添加:
case: [' - condition: parameter2 == \"\
parameter2_value\"\n execute:\n -\
parameter3: parameter3_value\n \
就像 jinja2 正确地创建了它,但不是 YAML 语法。
为什么这不起作用?除了动态创建这些代码之外,还有其他方法吗?
渲染的结果是一个字符串:
from jinja2 import Template
parameter2_data_tmpl = Template(""" - condition: $(parameter2) == "{{ parameter2_value }}"
execute:
- invoke:
parameter3: {{ parameter3_value }}
""");
parameter2_value = 'parameter2_value'
parameter3_value = 'parameter3_value'
parameter2_data = parameter2_data_tmpl.render(parameter2_value = parameter2_value, parameter3_value = parameter3_value)
print(type(parameter2_data))
这给出:
<class 'str'>
当您将该字符串添加到您使用 ruamel.yaml
加载的数据结构中的某处时,您
获取带引号的标量。
你想做的是添加一个数据结构,但是你不能从 模板,因为渲染的输出是无效的 YAML。
你可以不渲染直接创建数据结构,如果你不想
为此,您应该更改模板,以便它生成有效的 YAML 输入,加载
然后将该数据结构插入 data_src
的适当位置
(从你不完整的程序中不清楚):
import sys
import ruamel.yaml
from jinja2 import Template
parameter2_data_tmpl = Template("""\
- condition: $(parameter2) == "{{ parameter2_value }}"
execute:
- invoke:
parameter3: {{ parameter3_value }}
""");
parameter2_value = 'parameter2_value'
parameter3_value = 'parameter3_value'
parameter2_data = parameter2_data_tmpl.render(parameter2_value = parameter2_value, parameter3_value = parameter3_value)
yaml = ruamel.yaml.YAML()
yaml.indent(sequence=4, offset=2)
new_data = yaml.load(parameter2_data)
data = yaml.load("""\
case: some value to overwrite
""")
data['case'] = new_data
yaml.dump(data, sys.stdout)
给出:
case:
- condition: $(parameter2) == "parameter2_value"
execute:
- invoke:
parameter3: parameter3_value
请注意还有一个插件ruamel.yaml.jinja2
允许你加载
生成 YAML 输出和修改值的未呈现的 Jinja2 模板。