gpt4 book ai didi

python - 将 YAML 多行值转换为折叠 block 标量样式?

转载 作者:太空宇宙 更新时间:2023-11-03 10:55:41 30 4
gpt4 key购买 nike

使用 ruamel.yaml我试图获得某种样式的 YAML,更具体地说,单行字符串与 : 在同一行开始,多行字符串使用折叠标量样式 (|/|-) 并且行被限制为一定数量的字符(自动换行)。

到目前为止,我的尝试深受 similar function called walk_tree in the sources 的影响:

#!/usr/bin/env python

import ruamel.yaml

from ruamel.yaml.scalarstring import ScalarString, PreservedScalarString

def walk_tree(base):
from ruamel.yaml.compat import string_types

if isinstance(base, dict):
for k in base:
v = base[k]
if isinstance(v, string_types):
v = v.replace('\r\n', '\n').replace('\r', '\n').strip()
base[k] = ScalarString(v) if '\n' in v else v
else:
walk_tree(v)
elif isinstance(base, list):
for idx, elem in enumerate(base):
if isinstance(elem, string_types) and '\n' in elem:
print(elem) # @Anthon: this print is in the original code as well
base[idx] = preserve_literal(elem)
else:
walk_tree(elem)

with open("input.yaml", "r") as fi:
inp = fi.read()

loader=ruamel.yaml.RoundTripLoader
data = ruamel.yaml.load(inp, loader)

walk_tree(data)

dumper = ruamel.yaml.RoundTripDumper

with open("output.yaml", "w") as fo:
ruamel.yaml.dump(data, fo, Dumper=dumper, allow_unicode=True)

但随后出现异常:ruamel.yaml.representer.RepresenterError: cannot represent an object: ...。如果我将 ScalarString 替换为 PreservedScalarString ,我也没有异常(exception),就像原始 walk_tree 代码中的情况一样,但随后我又得到了文字 block ,这是不是我想要的。

那么如何修改我的代码使其正常工作呢?

最佳答案

ScalarString 类是 LiteralScalarString 的基类,正如您所发现的,它没有代表。您应该将其设为/保留一个 Python 字符串,因为它会适本地处理特殊字符(引用需要引用以符合 YAML 规范的字符串)。

假设您有这样的输入:

- 1
- abc: |
this is a short string scalar with a newline
in it
- "there are also a multiline\nsequence element\nin this file\nand it is longer"

你可能想做这样的事情:

import ruamel.yaml
from ruamel.yaml.scalarstring import LiteralScalarString, preserve_literal


def walk_tree(base):
from ruamel.yaml.compat import string_types

def test_wrap(v):
v = v.replace('\r\n', '\n').replace('\r', '\n').strip()
return v if len(v) < 72 else preserve_literal(v)

if isinstance(base, dict):
for k in base:
v = base[k]
if isinstance(v, string_types) and '\n' in v:
base[k] = test_wrap(v)
else:
walk_tree(v)
elif isinstance(base, list):
for idx, elem in enumerate(base):
if isinstance(elem, string_types) and '\n' in elem:
base[idx] = test_wrap(elem)
else:
walk_tree(elem)

yaml = YAML()

with open("input.yaml", "r") as fi:
data = yaml.load(fi)

walk_tree(data)

with open("output.yaml", "w") as fo:
yaml.dump(data, fo)

获取输出:

- 1
- abc: "this is a short string scalar with a newline\nin it"
- |-
there are also a multiline
sequence element
in this file
and it is longer

一些注意事项:

  • LiteralScalarString 的使用优于 PreservedScalarString。后者命名为唯一保留的字符串类型时的残余。
  • 您可能没有包含字符串的序列元素,因为您没有导入 preserve_literal,尽管它仍在复制的代码中使用。
  • 我将“包装”代码分解到 test_wrap 中,用于值和元素包装,最大行长度设置为 72 个字符。
  • data[1]['abc'] 加载为 LiteralScalarString。如果您想保留现有的文字样式字符串标量,您应该在测试类型 string_types 之前测试这些标量。
  • 我将新 API 与 YAML() 实例一起使用
  • 如果将示例中的 72 增加到默认值 80 以上,您可能必须将 width 属性设置为 1000 之类的值,以防止自动换行。(yaml.width = 1000)

关于python - 将 YAML 多行值转换为折叠 block 标量样式?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41353989/

30 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com