问题
I am trying to load some data from a YAML-file and put it back:
services:
dc01:
sw-06-50001:
servers:
- {ip: 10.255.206.12, port: 50001, weight: 100}
- {ip: 10.255.206.13, port: 50001, weight: 90}
virtual: {ip: 192.168.1.4, port: 50001}
sw-09-50002:
servers:
- {ip: 10.255.206.18, port: 50002, weight: 100}
- {ip: 10.255.206.19, port: 50002, weight: 90}
virtual: {ip: 192.168.1.4, port: 50002}
sw-06-50003:
servers:
- {ip: 10.255.206.12, port: 50003, weight: 100}
- {ip: 10.255.206.13, port: 50003, weight: 90}
virtual: {ip: 192.168.1.4, port: 50003}
sw-09-50004:
servers:
- {ip: 10.255.206.18, port: 50004, weight: 100}
- {ip: 10.255.206.19, port: 50004, weight: 90}
virtual: {ip: 192.168.1.4, port: 50004}
with this:
import ruamel.yaml as yaml
with open('filename.yml', 'r') as stream:
outdata = yaml.load(stream,Loader=yaml.Loader)
yaml.dump(outdata,'filename_out.yml')
I need to preserve all the formatting and data order in the list, but the output dump results in a sorting in alphabetical order by the sw-xx.. key:
services:
dc01:
sw-06-50001:
servers:
- {ip: 10.255.206.12, port: 50001, weight: 100}
- {ip: 10.255.206.13, port: 50001, weight: 90}
virtual: {ip: 192.168.1.4, port: 50001}
sw-06-50003:
servers:
- {ip: 10.255.206.12, port: 50003, weight: 100}
- {ip: 10.255.206.13, port: 50003, weight: 90}
virtual: {ip: 192.168.1.4, port: 50003}
sw-09-50002:
servers:
- {ip: 10.255.206.18, port: 50002, weight: 100}
- {ip: 10.255.206.19, port: 50002, weight: 90}
virtual: {ip: 192.168.1.4, port: 50002}
sw-09-50004:
servers:
- {ip: 10.255.206.18, port: 50004, weight: 100}
- {ip: 10.255.206.19, port: 50004, weight: 90}
virtual: {ip: 192.168.1.4, port: 50004}
How could I keep an original order of the entries while dumping?
回答1:
You are doing a round-trip, but you are not using ruamel.yaml's round-trip feature. Instead you are
using the outdated PyYAML compatibility load
and dump
functions.
Instead you should instantiate a ruamel.yaml.YAML()
instance and use that instance's load
and dump
methods,
they default to round-trip with preservation of order (and comments, tag names, etc.)
import sys
import ruamel.yaml
yaml_str = """\
services:
dc01:
sw-06-50001: # first
servers:
- {ip: 10.255.206.12, port: 50001, weight: 100}
- {ip: 10.255.206.13, port: 50001, weight: 90}
virtual: {ip: 192.168.1.4, port: 50001}
sw-09-50002:
servers:
- {ip: 10.255.206.18, port: 50002, weight: 100}
- {ip: 10.255.206.19, port: 50002, weight: 90}
virtual: {ip: 192.168.1.4, port: 50002}
sw-06-50003: # third
servers:
- {ip: 10.255.206.12, port: 50003, weight: 100}
- {ip: 10.255.206.13, port: 50003, weight: 90}
virtual: {ip: 192.168.1.4, port: 50003}
sw-09-50004:
servers:
- {ip: 10.255.206.18, port: 50004, weight: 100}
- {ip: 10.255.206.19, port: 50004, weight: 90}
virtual: {ip: 192.168.1.4, port: 50004}
"""
yaml = ruamel.yaml.YAML()
# yaml.indent(mapping=4, sequence=4, offset=2)
# yaml.preserve_quotes = True
data = yaml.load(yaml_str)
yaml.dump(data, sys.stdout)
which gives:
services:
dc01:
sw-06-50001: # first
servers:
- {ip: 10.255.206.12, port: 50001, weight: 100}
- {ip: 10.255.206.13, port: 50001, weight: 90}
virtual: {ip: 192.168.1.4, port: 50001}
sw-09-50002:
servers:
- {ip: 10.255.206.18, port: 50002, weight: 100}
- {ip: 10.255.206.19, port: 50002, weight: 90}
virtual: {ip: 192.168.1.4, port: 50002}
sw-06-50003: # third
servers:
- {ip: 10.255.206.12, port: 50003, weight: 100}
- {ip: 10.255.206.13, port: 50003, weight: 90}
virtual: {ip: 192.168.1.4, port: 50003}
sw-09-50004:
servers:
- {ip: 10.255.206.18, port: 50004, weight: 100}
- {ip: 10.255.206.19, port: 50004, weight: 90}
virtual: {ip: 192.168.1.4, port: 50004}
Or in case you have your YAML in a file:
from pathlib import Path
from ruamel.yaml import YAML
# the recommended extension for YAML files has been .yaml since 2006.
file_name = Path('filename.yaml')
file_out = Path('filename_out.yaml')
yaml = YAML()
outdata = yaml.load(file_name)
yaml.dump(outdata, file_out)
来源:https://stackoverflow.com/questions/61989767/is-there-a-way-to-preserve-order-while-round-trip-dumping-yaml-in-python