You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

使用ruamel.yaml处理YAML文件时多行字符串空行缩进异常的解决方法

使用ruamel.yaml处理YAML文件时多行字符串空行缩进异常的解决方法

我之前也碰到过类似的问题,用ruamel.yaml处理带空行的块样式字符串时,dump后空行丢失缩进确实挺头疼的。结合我的经验和踩过的坑,给你几个可行的解决方案:

方法一:调整ruamel.yaml的dump配置

首先确保你用的是最新版的ruamel.yaml(旧版本可能存在格式保留的bug),然后通过配置dump参数来强制保留缩进格式。这种方法最简单,适合大多数场景:

from ruamel.yaml import YAML

# 初始化YAML对象并配置格式保留参数
yaml = YAML()
yaml.preserve_quotes = True  # 保留原始引号(如果有的话)
yaml.indent(mapping=4, sequence=4, offset=2)  # 设置映射、序列的缩进规则

# 加载原始YAML文件
with open('input.yaml', 'r', encoding='utf-8') as f:
    data = yaml.load(f)

# 保存处理后的文件
with open('output.yaml', 'w', encoding='utf-8') as f:
    yaml.dump(data, f)

这里的indent方法可以根据你的YAML实际缩进层级调整,比如mapping=4表示每个映射层级缩进4个空格,这样块字符串里的空行就能和周围内容保持一致的缩进了。

方法二:手动遍历处理多行字符串的空行

如果调整配置后还是没解决问题,可以手动遍历YAML结构,找到所有多行字符串,将空行替换为带对应缩进的内容。这种方法更灵活,适合复杂结构的YAML:

from ruamel.yaml import YAML
from ruamel.yaml.comments import CommentedMap, CommentedSeq

def fix_empty_lines(node, current_indent=0):
    # 计算当前层级下多行字符串的缩进(根据你的实际YAML结构调整,这里假设每层缩进4)
    content_indent = ' ' * (current_indent + 4)
    
    if isinstance(node, CommentedMap):
        for key, value in node.items():
            if isinstance(value, str) and '\n' in value:
                # 拆分多行字符串,处理空行
                lines = value.split('\n')
                fixed_lines = []
                for line in lines:
                    # 识别空行,替换为带缩进的空行
                    if not line.strip():
                        fixed_lines.append(content_indent)
                    else:
                        fixed_lines.append(line)
                node[key] = '\n'.join(fixed_lines)
            else:
                # 递归处理子节点
                fix_empty_lines(value, current_indent + 4)
    elif isinstance(node, CommentedSeq):
        for item in node:
            fix_empty_lines(item, current_indent + 4)

# 加载并处理文件
yaml = YAML()
with open('input.yaml', 'r', encoding='utf-8') as f:
    data = yaml.load(f)

fix_empty_lines(data)

with open('output.yaml', 'w', encoding='utf-8') as f:
    yaml.dump(data, f)

注意要根据你的YAML实际缩进层级调整content_indent的计算逻辑,确保空行的缩进和其他代码行一致。

方法三:用LiteralScalarString明确指定块样式字符串

ruamel.yaml提供了LiteralScalarString类,可以明确标记字符串为块样式,确保完全保留原始的换行、缩进和空行。如果是手动修改字符串内容,这种方法也很有用:

from ruamel.yaml import YAML
from ruamel.yaml.scalarstring import LiteralScalarString

yaml = YAML()
yaml.preserve_quotes = True  # 保留原始格式

# 加载文件
with open('input.yaml', 'r', encoding='utf-8') as f:
    data = yaml.load(f)

# 如果是手动修改字符串,用LiteralScalarString包裹内容(可选,加载后的原始字符串已经是该类型)
# data["'Page' As screen"]["gal As gallery"]["Items"] = LiteralScalarString("""={
#         someItem: someValue,
# 
#         someItem2: someValue2
#     }""")

# 保存文件
with open('output.yaml', 'w', encoding='utf-8') as f:
    yaml.dump(data, f)

这种方法能确保块样式字符串的所有格式细节都被完整保留,包括连续空行的缩进。

备注:内容来源于stack exchange,提问作者niach

火山引擎 最新活动