指定 PyYAML 转储部分的样式(II):序列
Specifying styles for portions of a PyYAML dump (II): sequences
这是 Specifying styles for portions of a PyYAML dump 的后续问题:
考虑以下包含手动格式化 YAML 数据作为输入的代码。我正在修改 YAML 数据,但希望在写入的 YAML 文件中保持单行边缘。
import yaml
st2 = yaml.load("""
edges:
- [1, 2]
- [2, 1, [1,0]]
""")
print yaml.dump(st2)
class blockseq( dict ): pass
def blockseq_rep(dumper, data):
return dumper.represent_mapping( u'tag:yaml.org,2002:seq', data, flow_style=False )
class flowmap( dict ): pass
def flowmap_rep(dumper, data):
return dumper.represent_mapping( u'tag:yaml.org,2002:map', data, flow_style=True )
class blockseqtrue( dict ): pass
def blockseqtrue_rep(dumper, data):
return dumper.represent_mapping( u'tag:yaml.org,2002:seq', data, flow_style=True )
yaml.add_representer(blockseq, blockseq_rep)
yaml.add_representer(blockseqtrue, blockseqtrue_rep)
yaml.add_representer(flowmap, flowmap_rep)
st2['edges'] = [ blockseqtrue(x) for x in st2['edges'] ]
print yaml.dump(st2)
此脚本退出并显示以下错误输出:
edges:
- [1, 2]
- - 2
- 1
- [1, 0]
Traceback (most recent call last):
File "test-yaml-rep.py", line 42, in <module>
st2['edges'] = [ blockseqtrue(x) for x in st2['edges'] ]
TypeError: cannot convert dictionary update sequence element #0 to a sequence
你的问题是我的两个 类 都对指令而不是列表进行操作。您想要可以与列表一起使用的东西:
class blockseqtrue( list ): pass
def blockseqtrue_rep(dumper, data):
return dumper.represent_sequence( u'tag:yaml.org,2002:seq', data, flow_style=True )
Python 列表是 YAML 序列/序列。 Python 字典是 YAML mappings/maps。
如果您在 python 中进行往返 YAML,则使用起来要容易得多 ruamel.yaml(我是那个增强版 PyYAML 的作者)。
它保留 flow/block 样式 sequences/lists 和 mapppings/dicts(以及注释):
import ruamel.yaml
st2 = ruamel.yaml.load("""
edges:
- [1, 2] # <- change the second item
- [2, 1, [1,0]]
""", Loader=ruamel.yaml.RoundTripLoader)
st2['edges'][0][1] = 42
print(ruamel.yaml.dump(st2, Dumper=ruamel.yaml.RoundTripDumper))
会给你:
edges:
- [1, 42] # <- change the second item
- [2, 1, [1, 0]]
如您所见,这保留了最顶部序列的块样式(edges
的值)和其他序列的流样式。
这是 Specifying styles for portions of a PyYAML dump 的后续问题:
考虑以下包含手动格式化 YAML 数据作为输入的代码。我正在修改 YAML 数据,但希望在写入的 YAML 文件中保持单行边缘。
import yaml
st2 = yaml.load("""
edges:
- [1, 2]
- [2, 1, [1,0]]
""")
print yaml.dump(st2)
class blockseq( dict ): pass
def blockseq_rep(dumper, data):
return dumper.represent_mapping( u'tag:yaml.org,2002:seq', data, flow_style=False )
class flowmap( dict ): pass
def flowmap_rep(dumper, data):
return dumper.represent_mapping( u'tag:yaml.org,2002:map', data, flow_style=True )
class blockseqtrue( dict ): pass
def blockseqtrue_rep(dumper, data):
return dumper.represent_mapping( u'tag:yaml.org,2002:seq', data, flow_style=True )
yaml.add_representer(blockseq, blockseq_rep)
yaml.add_representer(blockseqtrue, blockseqtrue_rep)
yaml.add_representer(flowmap, flowmap_rep)
st2['edges'] = [ blockseqtrue(x) for x in st2['edges'] ]
print yaml.dump(st2)
此脚本退出并显示以下错误输出:
edges:
- [1, 2]
- - 2
- 1
- [1, 0]
Traceback (most recent call last):
File "test-yaml-rep.py", line 42, in <module>
st2['edges'] = [ blockseqtrue(x) for x in st2['edges'] ]
TypeError: cannot convert dictionary update sequence element #0 to a sequence
你的问题是我的两个 类 都对指令而不是列表进行操作。您想要可以与列表一起使用的东西:
class blockseqtrue( list ): pass
def blockseqtrue_rep(dumper, data):
return dumper.represent_sequence( u'tag:yaml.org,2002:seq', data, flow_style=True )
Python 列表是 YAML 序列/序列。 Python 字典是 YAML mappings/maps。
如果您在 python 中进行往返 YAML,则使用起来要容易得多 ruamel.yaml(我是那个增强版 PyYAML 的作者)。 它保留 flow/block 样式 sequences/lists 和 mapppings/dicts(以及注释):
import ruamel.yaml
st2 = ruamel.yaml.load("""
edges:
- [1, 2] # <- change the second item
- [2, 1, [1,0]]
""", Loader=ruamel.yaml.RoundTripLoader)
st2['edges'][0][1] = 42
print(ruamel.yaml.dump(st2, Dumper=ruamel.yaml.RoundTripDumper))
会给你:
edges:
- [1, 42] # <- change the second item
- [2, 1, [1, 0]]
如您所见,这保留了最顶部序列的块样式(edges
的值)和其他序列的流样式。