Python 格式化 PyYAML dump() 输出
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/14228915/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Formatting PyYAML dump() output
提问by nope
I have a list of dictionaries, which I want to serialize:
我有一个字典列表,我想对其进行序列化:
list_of_dicts = [ { 'key_1': 'value_a', 'key_2': 'value_b'},
{ 'key_1': 'value_c', 'key_2': 'value_d'},
...
{ 'key_1': 'value_x', 'key_2': 'value_y'} ]
yaml.dump(list_of_dicts, file, default_flow_style = False)
produces the following:
产生以下内容:
- key_1: value_a
key_2: value_b
- key_1: value_c
key_2: value_d
(...)
- key_1: value_x
key_2: value_y
But i'd like to get this:
但我想得到这个:
- key_1: value_a
key_2: value_b
<-|
- key_1: value_c |
key_2: value_d | empty lines between blocks
(...) |
<-|
- key_1: value_x
key_2: value_y
PyYAML documentationtalks about dump()arguments very briefly and doesn't seem to have anything on this particular subject.
PyYAML文档dump()非常简短地讨论了参数,似乎没有关于这个特定主题的任何内容。
Editing the file manually to add newlines improves readability quite a lot, and the structure still loads just fine afterwards, but I have no idea how to make dump method generate it.
手动编辑文件以添加换行符大大提高了可读性,之后结构仍然加载得很好,但我不知道如何让转储方法生成它。
And in general, is there a way to have more control over output formatting besides simple indentation?
一般来说,除了简单的缩进之外,还有没有办法更好地控制输出格式?
采纳答案by Yuri Baburov
There's no easy way to do this with the library (Node objects in yaml dumper syntax tree are passive and can't emit this info), so I ended up with
使用库没有简单的方法来做到这一点(yaml dumper 语法树中的节点对象是被动的,无法发出此信息),所以我最终得到了
stream = yaml.dump(list_of_dicts, default_flow_style = False)
file.write(stream.replace('\n- ', '\n\n- '))
回答by synthesizerpatel
While its a little klunky, I had the same goal as OP. I solved it by subclassing yaml.Dumper
虽然有点笨拙,但我的目标与 OP 相同。我通过子类化 yaml.Dumper 解决了它
from yaml import Dumper
class MyDumper(Dumper):
def write_indent(self):
indent = self.indent or 0
if not self.indention or self.column > indent \
or (self.column == indent and not self.whitespace):
self.write_line_break()
##########$#######################################
# On the first level of indentation, add an extra
# newline
if indent == 2:
self.write_line_break()
##################################################
if self.column < indent:
self.whitespace = True
data = u' '*(indent-self.column)
self.column = indent
if self.encoding:
data = data.encode(self.encoding)
self.stream.write(data)
You call it like this:
你这样称呼它:
print dump(python_dict, default_flow_style=False, width=79, Dumper=MyDumper)
回答by Anthon
PyYAML documentation only talks about dump()arguments briefly, because there is not much to say. This kind of control is not provided by PyYAML.
PyYAML 文档只dump()简要讨论了参数,因为没有太多可说的。PyYAML 不提供这种控制。
To allow preservation of such empty (and comment) lines in YAML that is loaded, I started the development of the ruamel.yamllibrary, a superset of the stalled PyYAML, with YAML 1.2 compatibility, many features added and bugs fixed. With ruamel.yamlyou can do:
为了允许在加载的 YAML 中保留此类空(和注释)行,我开始开发该ruamel.yaml库,这是停滞的 PyYAML 的超集,具有 YAML 1.2 兼容性,添加了许多功能并修复了错误。有了ruamel.yaml你可以这样做:
import sys
import ruamel.yaml
yaml_str = """\
- key_1: value_a
key_2: value_b
- key_1: value_c
key_2: value_d
- key_1: value_x # a few before this were ellipsed
key_2: value_y
"""
yaml = ruamel.yaml.YAML()
data = yaml.load(yaml_str)
yaml.dump(data, sys.stdout)
and get the output exactly the same as the input string (including the comment).
并获得与输入字符串完全相同的输出(包括注释)。
You can also build the output that you want from scratch:
您还可以从头开始构建您想要的输出:
import sys
import ruamel.yaml
yaml = ruamel.yaml.YAML()
list_of_dicts = yaml.seq([ { 'key_1': 'value_a', 'key_2': 'value_b'},
{ 'key_1': 'value_c', 'key_2': 'value_d'},
{ 'key_1': 'value_x', 'key_2': 'value_y'} ])
for idx in range(1, len(list_of_dicts)):
list_of_dicts.yaml_set_comment_before_after_key(idx, before='\n')
ruamel.yaml.comments.dump_comments(list_of_dicts)
yaml.dump(list_of_dicts, sys.stdout)
The conversion using yaml.seq()is necessary to create an object that allows attachment of the empty-lines through special attributes.
yaml.seq()需要使用转换来创建允许通过特殊属性附加空行的对象。
The library also allows preservation/easy-setting of quotes and literal style on strings, format of int (hex, octal, binary) and floats. As well as separate indent specification for mappings and sequences (although not for individual mappings or sequences).
该库还允许保存/轻松设置字符串上的引号和文字样式、int 格式(十六进制、八进制、二进制)和浮点数。以及映射和序列的单独缩进规范(尽管不是单个映射或序列)。

