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

Python脚本修改YAML文件时多行字段格式异常的解决方案咨询

Python脚本修改YAML文件时多行字段格式异常的解决方案咨询

我完全理解你遇到的困扰——用PyYAML修改YAML文件后,原本整洁的多行块字符串(用|定义的那种)变成了带转义字符或者被引号包裹的格式,严重影响了文档的可读性。其实这个问题的核心在于PyYAML默认的序列化逻辑不会保留原YAML中的块标元数据,咱们可以通过两种方式解决:

方案一:改用ruamel.yaml库(推荐)

PyYAML更适合简单的YAML解析/序列化,而ruamel.yaml是专门为保留YAML原有格式(包括块标量、注释、键顺序)设计的工具,处理这种场景非常顺手。

步骤1:安装依赖

pip install ruamel.yaml

步骤2:修改你的脚本

把原来的PyYAML相关代码替换成ruamel.yaml的实现,调整后的核心代码如下:

import json
import sys
import logging
from datetime import datetime
from ruamel.yaml import YAML

# Configure logging
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')

def update_yaml_files(files, field, author_name, author_email):
  logging.info("Starting update_yaml_files function")
  files_path = json.loads(files)
  logging.info(f"Parsed JSON input: {files_path}")
  # 初始化ruamel.yaml对象,开启保留引号和原格式的设置
  yaml = YAML()
  yaml.preserve_quotes = True
  yaml.width = 4096  # 避免自动换行截断
  for file in files_path:
    logging.info(f"Processing file: {file}")
    try:
      with open(file, 'r', encoding='utf-8') as f:
        data = yaml.load(f)
      logging.info(f"Loaded YAML data from {file}: {data}")
      data['approvals'][field]['name'] = author_name
      data['approvals'][field]['email'] = author_email
      logging.info(f"Updated name and email for field '{field}'")
      if 'approvaldate' in data['approvals'][field]:
        data['approvals'][field]['approvaldate'] = datetime.now().strftime("%d-%b-%Y")
        logging.info(f"Updated approval date for field '{field}'")
      print(f"Updated data with approval date for {file}: {data}")
      with open(file, 'w', encoding='utf-8') as f:
        yaml.dump(data, f)
        logging.info(f"Successfully wrote updated data to {file}")
    except Exception as e:
      logging.error(f"Error processing file {file}: {e}")

if __name__ == "__main__":
  if len(sys.argv) != 5:
    logging.error("Invalid number of arguments. Expected 4 arguments.")
    sys.exit(1)
  files = sys.argv[1]
  field = sys.argv[2]
  author_name = sys.argv[3]
  author_email = sys.argv[4]
  logging.info("Script started with arguments: "f"files={files}, field={field}, author_name={author_name}, author_email={author_email}")
  update_yaml_files(files, field, author_name, author_email)
  logging.info("Script finished")

这样修改后,ruamel.yaml会自动识别原文件中的块标量格式(|),并在写入时完整保留,不会出现转义字符或者引号包裹的问题。

方案二:自定义PyYAML的字符串序列化器(不推荐,仅作备选)

如果不想更换库,可以通过自定义PyYAML的代表器(Representer)来强制多行字符串使用块标量格式输出,但这种方式会影响所有字符串的序列化,灵活性不如ruamel.yaml:

修改代码片段

在原脚本的yaml导入后添加以下自定义代表器:

import yaml

def multi_line_str_presenter(dumper, data):
    # 仅对包含换行符的字符串使用块标量格式
    if '\n' in data:
        return dumper.represent_scalar('tag:yaml.org,2002:str', data, style='|')
    # 单行字符串保持原有格式
    return dumper.represent_scalar('tag:yaml.org,2002:str', data)

# 注册自定义代表器
yaml.add_representer(str, multi_line_str_presenter)

然后把原来的yaml.safe_dump替换为yaml.dump(因为safe_dump会忽略自定义代表器),并保留其他参数:

yaml.dump(data, f, default_flow_style=False, sort_keys=False, allow_unicode=True, indent=2, width=4096)

不过这种方式有个小缺点:所有带换行的字符串都会被强制用|输出,哪怕原文件中是其他格式,所以还是推荐第一种方案更稳妥。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.15 03:19:31