
PyYAML 的 yaml.safe_load() 默认对多行字符串进行“折叠”处理,会删除行首空格并压缩多余换行;要完整保留换行符和缩进空格,需使用 YAML 字面量块标量(literal block scalar)语法 |-。
pyyaml 的 `yaml.safe_load()` 默认对多行字符串进行“折叠”处理,会删除行首空格并压缩多余换行;要完整保留换行符和缩进空格,需使用 yaml 字面量块标量(literal block scalar)语法 `|-`。
在 PyYAML 中,字符串的解析行为严格遵循 YAML 1.2 规范中关于标量样式(scalar styles) 的定义。默认情况下,未加修饰的多行字符串(如 "first\n\n second")会被解析为 folded style(折叠风格) 或 flow style(流式风格),此时 YAML 解析器会执行以下标准化操作:
- 合并连续空白行(\n\n → \n);
- 去除每行开头的缩进空格(即“缩进基准”被剥离);
- 将换行符视作空格分隔符(除非显式启用字面量语义)。
因此,原始代码:
import yaml
data = yaml.safe_load("first\n\n second")
print(repr(data)) # 输出: 'first\nsecond'实际丢失了关键的缩进空格和冗余换行。
✅ 正确解法:使用 字面量块标量(literal block scalar),以 |- 开头(| 表示保留换行,- 表示去除末尾单个换行)。其后紧跟一个换行,再按所需格式书写内容——所有行首空格、内部换行、制表符均原样保留。
示例:
import yaml
# ✅ 正确:使用 |- 显式声明字面量块
data = yaml.safe_load("|-\n first\n second")
print(repr(data))
# 输出: 'first\n second'
# 更贴近真实场景的用法(带缩进的 YAML 片段)
yaml_text = """\
config:
description: |-
This is line one.
This line starts with 4 spaces.
And this is line three, aligned with line one.
"""
parsed = yaml.safe_load(yaml_text)
print(repr(parsed["config"]["description"]))
# 输出: 'This is line one.\n This line starts with 4 spaces.\nAnd this is line three, aligned with line one.'⚠️ 注意事项:
- |- 后必须紧跟换行符,否则解析失败;
- 字面量块中所有行首空格均被保留(包括首行之后的缩进),但需确保缩进一致(YAML 要求块内缩进不能少于首行缩进);
- 若需去除末尾换行,用 |-;若需保留末尾换行,用 |;若需折叠换行为空格,用 >(非本例需求);
- 避免在字面量块中混用制表符与空格缩进,易触发解析异常;
- 在 Python 字符串中书写多行 YAML 时,推荐使用三引号 """ 并注意首行缩进对齐(或使用 textwrap.dedent 清理)。
总结:当需要精确控制多行字符串的空白字符(尤其是保留缩进空格 + 换行符)时,绝不可依赖默认解析行为,而应主动采用 YAML 字面量块语法 |- —— 这是符合规范、稳定可靠且跨解析器兼容的标准方案。

















