为PyYAML转储的某些部分指定样式

cge*_*cge 8 yaml pyyaml

我正在使用YAML作为计算机和人类可编辑和可读的模拟器输入格式.对于人类可读性,输入的某些部分主要适合于阻止样式,而流动样式更适合其他部分.

PyYAML的默认设置是在嵌套地图或序列的任何地方使用块样式,在其他任何地方使用流样式.*default_flow_style*允许选择all-flow-style或all-block-style.

但我想输出更多的表格文件

bonds:
- { strength: 2.0 }
- ...
tiles:
- { color: red, edges: [1, 0, 0, 1], stoic: 0.1}
- ...
args: 
    block: 2
    Gse: 9.4
Run Code Online (Sandbox Code Playgroud)

可以看出,这并不是贯穿整个样式的一致模式,而是根据文件的部分而改变.本质上,我希望能够指定某些块样式序列中的所有值都是流式样.有没有办法对转储进行那种精细级别的控制?能够以特定顺序转储顶级映射而不需要该顺序(例如,omap)对于可读性而言将是好的.

cge*_*cge 13

事实证明,这可以通过为每个我想要不遵循default_flow_style的项目定义具有表示符的子类来完成,然后在转储之前将所有必要的内容转换为那些.在这种情况下,这意味着我得到类似的东西:

class blockseq( dict ): pass
def blockseq_rep(dumper, data):
    return dumper.represent_mapping( u'tag:yaml.org,2002:map', 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 )

yaml.add_representer(blockseq, blockseq_rep)
yaml.add_representer(flowmap, flowmap_rep)

def dump( st ):
    st['tiles'] = [ flowmap(x) for x in st['tiles'] ]
    st['bonds'] = [ flowmap(x) for x in st['bonds'] ]
    if 'xgrowargs' in st.keys(): st['xgrowargs'] = blockseq(st['xgrowargs'])
    return yaml.dump(st)
Run Code Online (Sandbox Code Playgroud)

令人讨厌的是,易于使用的dumper.represent_list和dumper.represent_dict不允许指定flow_style,因此我必须指定标记,但系统确实有效.