
在使用 PyYAML 生成供 Ansible(支持 Jinja2 模板语法)使用的 YAML 文件时,需确保形如 {{ val }} 的字符串以无引号纯文本形式输出,而非默认的带单引号格式 '{{ val }}'。
在使用 pyyaml 生成供 ansible(支持 jinja2 模板语法)使用的 yaml 文件时,需确保形如 `{{ val }}` 的字符串以无引号纯文本形式输出,而非默认的带单引号格式 `'{{ val }}'`。
PyYAML 默认会对包含特殊字符(如空格、花括号、美元符等)的字符串自动添加单引号,以保证 YAML 解析安全性。但 Ansible 的 Jinja2 变量语法 {{ val }} 必须作为裸字符串(unquoted scalar)出现在 YAML 中才能被正确识别和渲染,否则会被当作字面量字符串处理,导致模板失效。
解决此问题的核心是绕过 PyYAML 默认的标量样式选择逻辑。PyYAML 在序列化字符串时,会调用 Emitter.choose_scalar_style() 方法判断是否需要加引号:返回 '' 表示使用“plain”风格(即无引号),而默认实现仅对简单标识符(如 true、null 或纯字母数字)返回该值,其余多数情况返回 '\'(单引号)或 '"'(双引号)。
因此,我们可自定义一个 PlainDumper 类,重写 choose_scalar_style() 方法,强制始终返回空字符串:
import yaml
class PlainDumper(yaml.Dumper):
def choose_scalar_style(self):
return ''
data = {
'user': '{{ val }}',
'template': '{{ item.name | upper }}',
'fallback': 'default_value'
}
# 关键参数:Dumper=PlainDumper + default_flow_style=True(单行紧凑输出)
yaml_output = yaml.dump(
data,
Dumper=PlainDumper,
default_flow_style=True, # 确保输出为 user: {{ val }}, 而非块格式
allow_unicode=True, # 支持中文等 Unicode 字符
width=1000 # 避免自动换行(可选)
)
print(yaml_output.strip())
输出结果为:
让 macOS 自动化像说话一样简单 —— 用代码控制你的 Mac,无需学习 AppleScript 系统要求 macOS 14+ (Sonoma) Python 3.9+ 需要开启:辅助功能 + 屏幕录制权限
user: {{ val }}, template: {{ item.name | upper }}, fallback: default_value
⚠️ 注意事项:
- 此方案适用于可信数据源。强制禁用引号会降低 YAML 安全性——若值中含
:、{、}、[、]、,、#或换行符等,可能导致解析错误。生产环境建议仅对明确已知为 Jinja2 模板表达式的字段做针对性处理(例如结合yaml.SafeDumper+ 自定义represent方法)。 - 若需混合输出(部分字段带引号、部分不带),更稳健的做法是为特定类型注册自定义表示器(
add_representer),而非全局覆盖choose_scalar_style。 - Ansible 2.10+ 支持
!unsafe标签(需配合unsafe_yaml插件),但 PyYAML 原生不识别;本方案无需额外插件,兼容所有 Ansible 版本。
总结:通过继承 yaml.Dumper 并重写 choose_scalar_style,可精准控制 YAML 标量输出风格,是解决 Jinja2 模板与 PyYAML 兼容性问题的轻量、高效且广泛验证的实践方案。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!










