1

I have a YAML file, test.yaml:

test:
  server_group_1:
    type: OS::Nova::ServerGroup
    properties:
      name: { get_param: [server_groups, 5] }
      policies: [ { get_param: [server_group_types, 5] } ]

and when I use PyYAML to read and print the output it gives me below output, which is different from the input

test:
  server_group_1:
    properties:
      name:
        get_param:
        - server_groups
        - 5
      policies:
      - get_param:
        - server_group_types
        - 5
    type: OS::Nova::ServerGroup

code:

import yaml
print yaml.dump(yaml.load(open('/test.yaml')), default_flow_style=False)

I want the output same as the input, here order is also getting changed

Anthon
  • 69,918
  • 32
  • 186
  • 246
Naresh
  • 217
  • 2
  • 4
  • 16

1 Answers1

0

Your short PyYAML code has several problems, not related to the order of keys in mappings (which PyYAML always sorts).

There is almost never need to use PyYAML's load() without Loader parameter, which is documented to be unsafe. And you fail to provide a stream parameter to dump(), which causes the output to be written to memory, retrieved and then you print it. You should just use dump(yaml.safe_load(open('/test.yaml')), sys.stdout, default_flow_style=False) if you want to experiment with PyYAML.


Although it is possible to have PyYAML mapping loaded as Python ordered dictionaries, this is not trivial.

Far more problematic is the nested flow style, e.g. {get_param: [server_groups, 5]} where a flow style list is nested in a flow style mapping. PyYAML control for flow style is one of three: no flow style at all, or everything flow-style, or all leaf nodes flow style.

You should look at ruamel.yaml (disclaimer: I am the author of that package) where you can do:

import sys
import ruamel.yaml

yaml = ruamel.yaml.YAML()

with open('test.yaml') as fp:
    data = yaml.load(fp)
yaml.dump(data, sys.stdout)

this preserves the key order, and the flow style is preserved at all the levels. The only thing you cannot control is the extra spaces after/before the flow style curly braces and the inconsistent extra spaces after/before the flow style square brackets.

With the code above you get:

test:
  server_group_1:
    type: OS::Nova::ServerGroup
    properties:
      name: {get_param: [server_groups, 5]}
      policies: [{get_param: [server_group_types, 5]}]
Anthon
  • 69,918
  • 32
  • 186
  • 246
  • Thanks Anthon ... I have to merge two files will try using ruamel.yaml – Naresh Nov 22 '17 at 00:59
  • Now I am able to merge two files without changing the order .... thanks a lot for the help and do u have rhel rpm available for ruamel.yaml.... – Naresh Nov 22 '17 at 01:46
  • I have no RPM available, and I am not aware of a distro that has. You should use virtualenv (installed via RPM or directly) and create any of your own applications using virtualenv, then it is easy to deinstall, by removing the applications directory. – Anthon Nov 22 '17 at 06:11
  • I am having one issue with quotes in the yaml file can you please help in this [link](https://stackoverflow.com/questions/47441501/remove-single-quotes-from-dict-values-while-adding-content-to-yaml-file-using-py) – Naresh Nov 23 '17 at 03:53