You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用Python结合Jinja2模板生成指定结构的YAML文件?

问题描述

我尝试用Python结合Jinja2模板生成YAML文件,当前代码会重复输出完整的name和topology结构,而我需要将所有交换机节点放在同一个nodes节点下。

当前Jinja2模板(eos-test-sb.clab.j2):

name: eos-lab
topology:
  nodes:
    {{ switch_name }}:
      kind: ceos
      image: ceos:4.30.3M
      binds:
        - {{ switch_name }}.txt.json:/mnt/flash/EosIntfMapping.json:ro

Python代码:

import yaml
import jinja2
i = [{"switch_name": "a"}, {"switch_name": "b"}]
template_file = "eos-test-sb.clab.j2"
env = jinja2.Environment(loader=jinja2.FileSystemLoader(searchpath="."))
template = env.get_template(template_file)
for device in i:
    result = template.render(device)
    print(result)

当前输出:

name: eos-lab
topology:
  nodes:
    a:
      kind: ceos
      image: ceos:4.30.3M
      binds:
        - a.txt.json:/mnt/flash/EosIntfMapping.json:ro
name: eos-lab
topology:
  nodes:
    b:
      kind: ceos
      image: ceos:4.30.3M
      binds:
        - b.txt.json:/mnt/flash/EosIntfMapping.json:ro

期望输出:

name: eos-lab
topology:
  nodes:
    a:
      kind: ceos
      image: ceos:4.30.3M
      binds:
        - a.txt.json:/mnt/flash/EosIntfMapping.json:ro
    b:
      kind: ceos
      image: ceos:4.30.3M
      binds:
        - b.txt.json:/mnt/flash/EosIntfMapping.json:ro
解决方案

问题核心是你循环渲染了整个完整模板,导致每次输出都重复生成name和topology结构。正确的做法是一次性把所有设备数据传给模板,在模板内部循环生成nodes下的各个节点。

方法1:修改Jinja2模板,支持设备列表

更新模板文件eos-test-sb.clab.j2,使用Jinja2的循环语法遍历设备列表:

name: eos-lab
topology:
  nodes:
{% for device in devices %}
    {{ device.switch_name }}:
      kind: ceos
      image: ceos:4.30.3M
      binds:
        - {{ device.switch_name }}.txt.json:/mnt/flash/EosIntfMapping.json:ro
{% endfor %}

修改Python代码,将整个设备列表作为参数传给模板:

import jinja2

devices = [{"switch_name": "a"}, {"switch_name": "b"}]
template_file = "eos-test-sb.clab.j2"
env = jinja2.Environment(loader=jinja2.FileSystemLoader(searchpath="."))
template = env.get_template(template_file)
# 将设备列表以变量名devices传入模板
result = template.render(devices=devices)
print(result)

方法2:拆分模板,先渲染节点再拼接(可选)

如果不想修改原模板结构,可以拆分模板实现:

  1. 创建单个节点的模板node_template.j2:
{{ switch_name }}:
      kind: ceos
      image: ceos:4.30.3M
      binds:
        - {{ switch_name }}.txt.json:/mnt/flash/EosIntfMapping.json:ro
  1. 修改Python代码,先渲染所有节点再拼接成完整YAML:
import jinja2

devices = [{"switch_name": "a"}, {"switch_name": "b"}]
# 加载节点模板
node_template = jinja2.Environment(loader=jinja2.FileSystemLoader(searchpath=".")).get_template("node_template.j2")
# 渲染所有节点并拼接
nodes_content = "\n".join([node_template.render(device) for device in devices])
# 组合完整YAML内容
full_yaml = f"""name: eos-lab
topology:
  nodes:
{nodes_content}"""
print(full_yaml)

两种方法都能得到期望的输出,推荐方法1,更符合Jinja2的模板设计逻辑,维护成本更低。

内容的提问来源于stack exchange,提问作者kryton007

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.07 03:53:13