在 PyYAML 中使用表示器时控制折叠位置
Control fold position while using representer in PyYAML
我可以使用以下代码以折叠形式转储包含长字符串的 YAML 代码:
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'),
}
print(yaml.dump(data))
以上代码的输出是:
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 输出行的长度的简单方法
折叠,是提供(全局)线长参数width
:
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
如您所见,我删除了您对 print
的呼叫。 PyYAML 有一个流
接口并且不直接流式传输到输出,它需要做一个
输出的内存中解释既不必要地慢又内存
效率低下。
当然这也会影响任何其他被转储的行(长
非折叠标量、流式列表、深度嵌套数据结构。
不简单的方法是不调用represent_scalar
例程,并且
改编 PyYAML 的 ScalarNode
(或创建您自己的 Node
类型),即
然后在发射时在适当的位置输出一个换行符。
我的 ruamel.yaml
内置了这个功能,允许这样的输出往返
保留折叠位置(即使默认输出宽度相同
作为 PyYAML 的)
import sys
import ruamel.yaml
yaml_str = """\
[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
"""
yaml = ruamel.yaml.YAML()
data = yaml.load(yaml_str)
yaml.dump(data, sys.stdout)
给出:
[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
尽管您可以从头开始创建这样的折叠字符串,但这并不简单(有
没有 API,内部表示可能会改变)。我推荐的是
只需创建折叠的字符串数据,然后通过不同地定义 folded_str
来加载它:
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
我可以使用以下代码以折叠形式转储包含长字符串的 YAML 代码:
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'),
}
print(yaml.dump(data))
以上代码的输出是:
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 输出行的长度的简单方法
折叠,是提供(全局)线长参数width
:
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
如您所见,我删除了您对 print
的呼叫。 PyYAML 有一个流
接口并且不直接流式传输到输出,它需要做一个
输出的内存中解释既不必要地慢又内存
效率低下。
当然这也会影响任何其他被转储的行(长 非折叠标量、流式列表、深度嵌套数据结构。
不简单的方法是不调用represent_scalar
例程,并且
改编 PyYAML 的 ScalarNode
(或创建您自己的 Node
类型),即
然后在发射时在适当的位置输出一个换行符。
我的 ruamel.yaml
内置了这个功能,允许这样的输出往返
保留折叠位置(即使默认输出宽度相同
作为 PyYAML 的)
import sys
import ruamel.yaml
yaml_str = """\
[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
"""
yaml = ruamel.yaml.YAML()
data = yaml.load(yaml_str)
yaml.dump(data, sys.stdout)
给出:
[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
尽管您可以从头开始创建这样的折叠字符串,但这并不简单(有
没有 API,内部表示可能会改变)。我推荐的是
只需创建折叠的字符串数据,然后通过不同地定义 folded_str
来加载它:
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