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

如何在Jinja2中合并两个字典?替代Ansible combine方案

Jinja2实现YAML字典合并(替代Ansible combine过滤器)

问题根源

你用vars.default.update(vars.new)得到None是因为Python的dict.update()方法是原地修改原字典,它的返回值本来就是None——这是Python字典方法的固有特性,和Jinja2无关,所以直接在模板里调用会输出None,而非合并后的字典。

两种可行解决方案

1. 自定义combine过滤器(推荐,支持递归合并)

Jinja2允许自定义过滤器,我们可以实现一个和Ansible combine逻辑一致的函数,注册到Jinja2环境中:

步骤1:编写Python代码注册过滤器
from jinja2 import Environment, FileSystemLoader
import yaml

def combine_dicts(base_dict, update_dict, recursive=False):
    # 先做浅拷贝,避免修改原字典
    result = base_dict.copy()
    result.update(update_dict)
    
    # 如果需要递归合并嵌套字典
    if recursive:
        for key, value in update_dict.items():
            if isinstance(value, dict) and key in result and isinstance(result[key], dict):
                result[key] = combine_dicts(result[key], value, recursive=True)
    return result

# 初始化Jinja2环境
env = Environment(loader=FileSystemLoader('.'))
# 注册自定义过滤器
env.filters['combine'] = combine_dicts

# 加载YAML变量文件
with open('vars.yml', 'r', encoding='utf-8') as f:
    vars_data = yaml.safe_load(f)

# 渲染模板
template = env.get_template('template.yml')
output_content = template.render(vars=vars_data)

# 保存结果到output.yml
with open('output.yml', 'w', encoding='utf-8') as f:
    f.write(output_content)
步骤2:在template.yml中使用过滤器
# 浅合并(新字典覆盖旧字典同键值)
merged_dict: {{ vars.default | combine(vars.new) }}

# 如果需要递归合并嵌套字典,加上recursive参数
# merged_dict: {{ vars.default | combine(vars.new, recursive=True) }}

2. 直接用Python字典解包(仅浅合并,无需额外代码)

如果你的Python版本是3.5+,可以直接在Jinja2模板里用{**d1, **d2}的语法实现浅合并,不需要自定义过滤器:

merged_dict: {{ {**vars.default, **vars.new} }}

注意:这种方式只支持浅合并——如果字典里嵌套了子字典,新字典的子字典会直接覆盖旧字典的对应子字典,不会递归合并内层内容。

预期输出(output.yml)

不管用哪种方式,浅合并的结果都会是:

merged_dict:
  key1: value1
  key2: new_value2
  key3: value3

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.01 01:15:32