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

如何在PyYaml中添加带|-块截断指示符的字面量字符串并自定义Dumper?

问题描述

我尝试从Python对象生成YAML文件,其中存在字面量字符串属性pattern = "^[0-9]+$",需要将其添加到同名节点pattern中作为块字面量,同时filter_sql_expr的布尔值True也要用带|-的块样式输出。

现有代码

import yaml
class MyDumper(yaml.Dumper):
    def increase_indent(self, flow=False, indentless=False):
        return super(MyDumper, self).increase_indent(flow, False)


source = {'row_filters':{'NONE':{'filter_sql_expr': True}},
          'rule_dimensions': ['completeness','conformance'],
          'rules': {'VALID_CUSTOMER_ID': {'rule_type': 'REGEX', 'dimension': 'accuracy', 'params': {'pattern': "^[0-9]+$"}}}}    

print(yaml.dump(source, Dumper=MyDumper, default_flow_style=False,sort_keys=False,indent=2,allow_unicode=True))

实际输出YAML

row_filters:
  NONE:
    filter_sql_expr: True
rule_dimensions:
  - completeness
  - conformance
rules:
  VALID_CUSTOMER_ID:
    rule_type: REGEX
    dimension: accuracy
    params:
      pattern: ^[0-9]+$

期望输出YAML

row_filters:
  NONE:
    filter_sql_expr: |-
      True
rule_dimensions:
  - completeness
  - conformance
rules:
  VALID_CUSTOMER_ID:
    rule_type: REGEX
    dimension: accuracy
    params:
      pattern: |-
        ^[0-9]+$

核心需求

为目标节点的内容添加带块截断指示符|-的块字面量格式,确保指定内容以该格式输出。

疑问

  1. 如何强制指定的字符串(或布尔值转换后的字符串)使用带|-的块样式输出?
  2. 如何给自定义的MyDumper类添加对应的转换逻辑?

解决方案

1. 自定义类型标记目标内容

先创建一个自定义类,用来标记需要特殊处理的内容,让YAML Dumper能识别并应用块字面量格式:

class BlockLiteral(str):
    pass

然后把需要转换的内容包装成这个类的实例(注意布尔值True要转成字符串,否则YAML会按原生布尔类型输出):

source = {
    'row_filters': {'NONE': {'filter_sql_expr': BlockLiteral("True")}},
    'rule_dimensions': ['completeness','conformance'],
    'rules': {
        'VALID_CUSTOMER_ID': {
            'rule_type': 'REGEX', 
            'dimension': 'accuracy', 
            'params': {'pattern': BlockLiteral("^[0-9]+$")}
        }
    }
}

2. 给MyDumper添加转换方法

在自定义Dumper中注册BlockLiteral类型的转换函数,强制输出带|-的块字面量:

import yaml

class MyDumper(yaml.Dumper):
    def increase_indent(self, flow=False, indentless=False):
        return super(MyDumper, self).increase_indent(flow, False)

# 定义转换逻辑:用|-块样式输出内容
def represent_block_literal(dumper, data):
    return dumper.represent_scalar('tag:yaml.org,2002:str', data, style='|-')

# 把自定义类型和转换函数绑定
MyDumper.add_representer(BlockLiteral, represent_block_literal)

3. 完整代码及测试

整合所有部分后的完整代码:

import yaml

class BlockLiteral(str):
    pass

class MyDumper(yaml.Dumper):
    def increase_indent(self, flow=False, indentless=False):
        return super(MyDumper, self).increase_indent(flow, False)

def represent_block_literal(dumper, data):
    return dumper.represent_scalar('tag:yaml.org,2002:str', data, style='|-')

MyDumper.add_representer(BlockLiteral, represent_block_literal)

source = {
    'row_filters': {'NONE': {'filter_sql_expr': BlockLiteral("True")}},
    'rule_dimensions': ['completeness','conformance'],
    'rules': {
        'VALID_CUSTOMER_ID': {
            'rule_type': 'REGEX', 
            'dimension': 'accuracy', 
            'params': {'pattern': BlockLiteral("^[0-9]+$")}
        }
    }
}

print(yaml.dump(source, Dumper=MyDumper, default_flow_style=False,sort_keys=False,indent=2,allow_unicode=True))

运行后就能得到你期望的YAML输出,目标节点会自动带上|-块截断指示符,内容以缩进的块字面量形式展示。

补充说明

  • 如果需要让所有字符串都用块字面量输出,直接把str类型注册到转换函数即可,无需用BlockLiteral包装;
  • style='|-'参数是核心,它指定了输出时使用带截断指示符的块字面量格式;
  • 布尔值必须转成字符串再包装,否则YAML会按原生布尔类型处理,无法应用块样式。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.06 21:45:46