Python 在Pyaml中使用representer时控制折叠位置

Python 在Pyaml中使用representer时控制折叠位置,python,format,yaml,pyyaml,Python,Format,Yaml,Pyyaml,我能够使用以下代码以折叠形式转储带有长字符串的YAML代码: 导入yaml 班级学生(str):通过 def折叠_str_representer(卸载机,数据): return dumper.representation_scalar(u'tag:yaml.org,2002:str',data,style='>')) yaml.添加重设中心(折叠重设中心、折叠重设中心) 数据={ “foo”:折叠的字符串(('abcdefghi'*10)+'end\n'), } 打印(yaml.dump(数据)

我能够使用以下代码以折叠形式转储带有长字符串的YAML代码:

导入yaml
班级学生(str):通过
def折叠_str_representer(卸载机,数据):
return dumper.representation_scalar(u'tag:yaml.org,2002:str',data,style='>'))
yaml.添加重设中心(折叠重设中心、折叠重设中心)
数据={
“foo”:折叠的字符串(('abcdefghi'*10)+'end\n'),
}
打印(yaml.dump(数据))
上述代码的输出为:

foo: >
  abcdefghi abcdefghi abcdefghi abcdefghi abcdefghi abcdefghi abcdefghi abcdefghi
  abcdefghi abcdefghi end
是否可以控制折叠发生后的长度?例如,如果我希望行在70个字符后折叠,则输出如下所示:

foo: >
  abcdefghi abcdefghi abcdefghi abcdefghi abcdefghi abcdefghi abcdefghi
  abcdefghi abcdefghi abcdefghi end

有没有办法让PyYAML做到这一点?

这是一种简单的方法,可以控制PyYAML输出的行的长度 折叠,是为(全局)行长度提供参数
宽度

import sys
import yaml

class folded_str(str): pass

def folded_str_representer(dumper, data):
    return dumper.represent_scalar(u'tag:yaml.org,2002:str', data, style='>')

yaml.add_representer(folded_str, folded_str_representer)

data = {
    'foo': folded_str(('abcdefghi ' * 10) + 'end\n'),
}

yaml.dump(data, sys.stdout, width=70)
其中:

foo: >
  abcdefghi abcdefghi abcdefghi abcdefghi abcdefghi abcdefghi abcdefghi
  abcdefghi abcdefghi abcdefghi end
[long, scalar]: This is just a filler to show that the default width is 80 chars
foo: >
  abcdefghi abcdefghi abcdefghi abcdefghi abcdefghi abcdefghi abcdefghi
  abcdefghi abcdefghi abcdefghi end
foo: >
  abcdefghi abcdefghi abcdefghi abcdefghi abcdefghi abcdefghi abcdefghi
  abcdefghi abcdefghi abcdefghi end
如您所见,我取消了您对
print
的呼叫。Pyaml有一个流媒体 接口,而不是直接流式传输到输出,它需要 内存中对输出的解释,该输出速度不必要地慢,且内存不足 效率高

当然,这也会影响任何其他被转储(长)的行 非折叠标量、流样式列表、深度嵌套的数据结构

不容易的方法是不调用
表示\u标量
例程,以及 改编PyYAML的
ScalarNode
(或者创建自己的
节点
类型) 然后在发射时在适当的位置输出换行符


My
ruamel.yaml
内置了此功能,以允许此类输出往返 保留折叠位置(即使默认输出宽度相同) 作为Pyaml的)

其中:

foo: >
  abcdefghi abcdefghi abcdefghi abcdefghi abcdefghi abcdefghi abcdefghi
  abcdefghi abcdefghi abcdefghi end
[long, scalar]: This is just a filler to show that the default width is 80 chars
foo: >
  abcdefghi abcdefghi abcdefghi abcdefghi abcdefghi abcdefghi abcdefghi
  abcdefghi abcdefghi abcdefghi end
foo: >
  abcdefghi abcdefghi abcdefghi abcdefghi abcdefghi abcdefghi abcdefghi
  abcdefghi abcdefghi abcdefghi end
尽管您可以从头开始创建这样一个折叠字符串,但它并不是微不足道的(有 没有API,内部表示可能会更改) 只需创建折叠字符串数据,然后通过定义不同的
折叠字符串来加载它:

import sys
import ruamel.yaml

yaml = ruamel.yaml.YAML()

def folded_str(s, pos=70):
    parts = []
    r = ""
    for part in s.split(' '):
        if not r:
            r = part
        elif len(r) + len(part) >= pos:
            parts.append(r + '\n')
            r = part
        else:
            r += ' ' + part
    parts.append(r)
    return yaml.load(">\n" + "".join(parts))

data = {
    'foo': folded_str(('abcdefghi ' * 10) + 'end\n'),
}

yaml.dump(data, sys.stdout)
其中:

foo: >
  abcdefghi abcdefghi abcdefghi abcdefghi abcdefghi abcdefghi abcdefghi
  abcdefghi abcdefghi abcdefghi end
[long, scalar]: This is just a filler to show that the default width is 80 chars
foo: >
  abcdefghi abcdefghi abcdefghi abcdefghi abcdefghi abcdefghi abcdefghi
  abcdefghi abcdefghi abcdefghi end
foo: >
  abcdefghi abcdefghi abcdefghi abcdefghi abcdefghi abcdefghi abcdefghi
  abcdefghi abcdefghi abcdefghi end

对于那些想知道
这只是一个填充词周围的(多余的)引号在哪里的人,…
可以通过设置
yaml.preserve\u quotes=True来在往返过程中保留这些引号