Простой способ контролировать, как долго строки, которые 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
и адаптировать ScalarNode
PyYAML (или создать свой собственный тип Node
), который затем выводит новую строку в соответствующей позиции при излучении.
My 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