如何使PyYAML或ruamel.yaml 总是内联转储列表?无论是从现有文件加载还是从我的代码添加的YAML元素列表。
当我从文件加载YAML然后转储时,它会内联转储列表(请参见下面的代码)。但是,如果我将一个带有列表的新YAML元素添加到现有的父对象中,然后转储它,则它不会内联转储列表。
我尝试使用Python 3.7.3,PyYAML 5.1.1和ruamel.yaml 0.15.97。
>>> import ruamel.yaml
>>> ruamel.yaml.__version__
'0.15.97'
>>> raw_yaml = """
... users:
... user1:
... comment: comment1
... keys: ["user1 key1", "user1 key2"]
... groups: ["user1 group1", "user1 group2"]
... """
>>> yaml = ruamel.yaml.round_trip_load(raw_yaml, preserve_quotes=True)
>>> dump = ruamel.yaml.round_trip_dump(yaml, default_flow_style=None)
>>> print(dump)
users:
user1:
comment: comment1
keys: ["user1 key1", "user1 key2"]
groups: ["user1 group1", "user1 group2"]
# So far so good, 'keys' and 'groups' are dumped inline
>>> yaml['users']['user2'] = {}
>>> yaml['users']['user2']['comment'] = 'comment2'
>>> yaml['users']['user2']['keys'] = []
>>> yaml['users']['user2']['keys'].append('user2 key1')
>>> yaml['users']['user2']['keys'].append('user2 key2')
>>> yaml['users']['user2']['groups'] = []
>>> yaml['users']['user2']['groups'].append('user2 group1')
>>> yaml['users']['user2']['groups'].append('user2 group2')
>>> dump = ruamel.yaml.round_trip_dump(
... yaml, default_flow_style=False, default_style="'",
... indent=2, block_seq_indent=2)
# desired result:
# users:
# user1:
# comment: comment1
# keys: ["user1 key1", "user1 key2"]
# groups: ["user1 group1", "user1 group2"]
# user2:
# comment: comment2
# keys: ["user2 key1", "user2 key2"]
# groups: ["user2 group1", "user2 group2"]
>>> print(dump)
'users':
'user1':
'comment': 'comment1'
'keys': ["user1 key1", "user1 key2"]
'groups': ["user1 group1", "user1 group2"]
'user2':
'comment': 'comment2'
'keys':
- 'user2 key1'
- 'user2 key2'
'groups':
- 'user2 group1'
- 'user2 group2'
请参阅上文,当我转储刚加载的YAML(用户['user1'])时,列表是内联的:
keys: ["user1 key1", "user1 key2"]
groups: ["user1 group1", "user1 group2"]
但是当我添加users ['user2']然后转储整个YAML对象时,列表不是内联的:
'keys':
- 'user2 key1'
- 'user2 key2'
'groups':
- 'user2 group1'
- 'user2 group2'
如果我设置'default_flow_style = True',它将内联转储整个元素:
'user2': {'comment': 'comment2', 'keys': ['user2 key1', 'user2 key2'], 'groups': [ 'user2 group1', 'user2 group2']}
这不是我想要的。我想将“注释”,“键”和“组”转储到带有内联列表的单独行上:
user2:
comment: comment2
keys: ["user2 key1", "user2 key2"]
groups: ["user2 group1", "user2 group2"]
对于PyYaml,情况实际上是相同的。
我希望列表始终以内联方式转储(对于users ['user1'])。我该怎么办?
答案 0 :(得分:0)
我只能回答PyYAML: 该行为在5.1版中已更改。
https://github.com/yaml/pyyaml/pull/256
False
将始终输出块样式。
True
将始终输出流样式。
None
将仅针对包含以下内容的集合输出流样式
仅标量。
False
现在是默认设置,因为许多用户抱怨以前的默认设置None
不合适。
因此,您需要default_flow_style=None
来使用PyYAML。
data = dict( a=dict(aa=dict(aaa = ['x','y']), ab=42) )
print( yaml.dump( data ) )
print( yaml.dump( data, default_flow_style=True ) )
print( yaml.dump( data, default_flow_style=False ) )
print( yaml.dump( data, default_flow_style=None ) )
输出:
a:
aa:
aaa:
- x
- y
ab: 42
{a: {aa: {aaa: [x, y]}, ab: 42}}
a:
aa:
aaa:
- x
- y
ab: 42
a:
aa:
aaa: [x, y]
ab: 42```
答案 1 :(得分:0)
您在YAML中将内联称为流样式
文档。两者中都有一个选项(default_flow_style
)
ruamel.yaml在全球范围内拥有所有流样式,
一切都是块样式,或者具有叶节点流样式(其余块
样式)。这是PyYAML的旧行为。
但是这不是您想要的,因为它会影响序列和 映射,而您只需要映射。
ruamel.yaml
在往返模式下可以保留单个
流样式/块样式,因为它们出现在文件中,因此您可以
例如离开节点及其父节点为流式或所有序列
(Python列表)流样式和所有映射(Python dict)块样式
后者当然仅在映射不在“下”时有效
顺序,因为您不能在流样式中拥有块样式。
如果从头开始或使用正确格式的已加载YAML,
只要确保添加的列表实际上是特殊的内部列表子类
ruamel.yaml
用于保留注释,样式等并设置流样式的
在添加的列表上
import sys
import ruamel.yaml
from ruamel.yaml.scalarstring import DoubleQuotedScalarString as dq
def L(*l):
ret = ruamel.yaml.comments.CommentedSeq(l)
ret.fa.set_flow_style()
return ret
raw_yaml = """\
users:
user1:
comment: comment1
keys: ["user1 key1", "user1 key2"]
groups: ["user1 group1", "user1 group2"]
"""
yaml = ruamel.yaml.YAML()
# yaml.indent(mapping=4, sequence=4, offset=2)
yaml.preserve_quotes = True
data = yaml.load(raw_yaml)
data['users']['user2'] = {}
data['users']['user2']['comment'] = 'comment2'
data['users']['user2']['keys'] = L()
data['users']['user2']['keys'].append('user2 key1')
data['users']['user2']['keys'].append('user2 key2')
data['users']['user2']['groups'] = L('abc', L('user2 group1', dq('user2 group2')))
# print(data)
yaml.dump(data, sys.stdout)
给出:
users:
user1:
comment: comment1
keys: ["user1 key1", "user1 key2"]
groups: ["user1 group1", "user1 group2"]
user2:
comment: comment2
keys: [user2 key1, user2 key2]
groups: [abc, [user2 group1, "user2 group2"]]
因为您希望每个列表都以流样式表示 顺序,也可以更改所有列表的代表, 通过将Representer子类化,但是以上内容使您可以更好地控制 并允许您以流样式准确地流动所需的那些列表。
ruamel.yaml
(和PyYAML)使用流接口,
使用print(dump(data))
而不是dump(data, sys.stdout)
进行转储
对内存中的缓冲区进行处理,然后对该缓冲区进行流式处理。它是
时间和空间效率低下,不要这样做。