Specifying styles for portions of a PyYAML dump

2019-02-21 23:08发布

问题:

I'm using YAML for a computer and human-editable and readable input format for a simulator. For human readability, some parts of the input are mostly amenable to block style, while flow style suits others better.

The default for PyYAML is to use block style wherever there are nested maps or sequences, and flow style everywhere else. *default_flow_style* allows one to choose all-flow-style or all-block-style.

But I'd like to output files more of the form

bonds:
- { strength: 2.0 }
- ...
tiles:
- { color: red, edges: [1, 0, 0, 1], stoic: 0.1}
- ...
args: 
    block: 2
    Gse: 9.4

As can be seen, this doesn't follow a consistent pattern for styles throughout, and instead changes depending upon the part of the file. Essentially, I'd like to be able to specify that all values in some block style sequences be in flow style. Is there some way to get that sort of fine-level control over dumping? Being able to dump the top-level mapping in a particular order while not requiring that order (eg, omap) would be nice as well for readability.

回答1:

It turns out this can be done by defining subclasses with representers for each item I want not to follow default_flow_style, and then converting everything necessary to those before dumping. In this case, that means I get something like:

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)

Annoyingly, the easier-to-use dumper.represent_list and dumper.represent_dict don't allow flow_style to be specified, so I have to specify the tag, but the system does work.



标签: yaml pyyaml