简体   繁体   中英

Issue in writing the dictionary into YAML file in python

I want to write dictionary into YAML file and here is what I'm doing as of now

from ruamel.yaml import YAML

Flavor_Details = {'Flavor_Details':{
                  'type': 'OS::Nova::Flavor', 
                  'properties': {
                                 'name': 'test-flavor', 
                                 'extra_specs': {"hw:cpu_policy": 'shared'}, 
                                 'ram': 4096, 
                                 'vcpus': 4, 
                                 'disk': 8
                                }
                 }}

output_section = {
                    'server_public_ip':{
                        'description': 'Floating IP address of server',
                        'value': { 'get_attr': [ 'server_floating_ip', 'ip' ] }
                    }
                }

resources_dict = {}
resources_dict.update(Flavor_Details)
resources_dict.update(output_section)

yaml = YAML(typ= 'safe')

with open('test.yaml', 'w') as outfile:
     yaml.dump(resources_dict,outfile)

And here is the result in YAML file

Flavor_Details:
    properties:
      disk: 8
      extra_specs: {hw:cpu_policy: shared}
      name: test-flavor
      ram: 4096
      vcpus: 4
    type: OS::Nova::Flavor
server_public_ip:
    description: Floating IP address of server
    value:
      get_attr: [server__floating_ip, ip]

But I wanted the result like this:

Flavor_Details:
    properties:
      disk: 8
      extra_specs: {"hw:cpu_policy": shared}
      name: test-flavor
      ram: 4096
      vcpus: 4
    type: OS::Nova::Flavor
server_public_ip:
    description: Floating IP address of server
    value: {get_attr: [server__floating_ip, ip]}

I wanted the "hw:cpu_policy" as a string because of the : between the hw and the cpu_policy and in the value I wanted to be like {get_attr: [server__floating_ip, ip]} this.

Is there any way to get things like that?

You can get what you want, but not by using the safe dumper. The underlying C based code doesnt' allow for the fine grained control that you want.

You'll need to use the default (round-trip) dumper, which allows for this kind of detailed control, as it needs it to try-and-preserve the layout on round-trips.

I hope you realise that the quotes around hw:cpu_policy in the YAML file are not necessary according to the YAML specification, but there are some incorrect implementations of YAML parser that have problems with that.

import sys
import ruamel.yaml

def Q(s):
    return ruamel.yaml.scalarstring.DoubleQuotedScalarString(s)

def F(*args, **kw):
    x = ruamel.yaml.comments.CommentedMap()
    x.fa.set_flow_style()
    for a in args:
        x.update(a)
    x.update(kw)
    return x


Flavor_Details = {'Flavor_Details':{
                  'type': 'OS::Nova::Flavor', 
                  'properties': {
                                 'name': 'test-flavor', 
                                 'extra_specs': F({Q("hw:cpu_policy"): 'shared'}), 
                                 'ram': 4096, 
                                 'vcpus': 4, 
                                 'disk': 8
                                }
                 }}

output_section = {
                    'server_public_ip':{
                        'description': 'Floating IP address of server',
                        'value': F(get_attr=['server_floating_ip', 'ip'])
                    }
                }

resources_dict = {}
resources_dict.update(Flavor_Details)
resources_dict.update(output_section)

yaml = ruamel.yaml.YAML()
# yaml.indent(mapping=4, sequence=4, offset=2)
yaml.dump(resources_dict, sys.stdout)

which gives:

Flavor_Details:
  type: OS::Nova::Flavor
  properties:
    name: test-flavor
    extra_specs: {"hw:cpu_policy": shared}
    ram: 4096
    vcpus: 4
    disk: 8
server_public_ip:
  description: Floating IP address of server
  value: {get_attr: [server_floating_ip, ip]}

An alternative would be going back to PyYAML and use a simple replacement rule on the output string. Note as well the requoted entries for extra_specs and value .

import yaml as yl

Flavor_Details = {'Flavor_Details': {
                  'type': 'OS::Nova::Flavor',
                  'properties': {
                      'name': 'cloudpeak-test-flavor',
                      'extra_specs': "{'hw:cpu_policy': shared}",
                      'ram': 4096,
                      'vcpus': 4,
                      'disk': 8
                  }
                  }}

output_section = {
    'server_public_ip': {
        'description': 'Floating IP address of server',
        'value': '{get_attr: [server_floating_ip, ip]}'
    }
}

resources_dict = {}
resources_dict.update(Flavor_Details)
resources_dict.update(output_section)

out_str = yl.safe_dump(resources_dict)
out_str = out_str.replace("''", '"')
out_str = out_str.replace("'", '')

print(out_str)

with open('test-yl.yaml', 'w') as outfile:
    outfile.write(out_str)

which gives:

Flavor_Details:
  properties:
    disk: 8
    extra_specs: {"hw:cpu_policy": shared}
    name: cloudpeak-test-flavor
    ram: 4096
    vcpus: 4
  type: OS::Nova::Flavor
server_public_ip:
  description: Floating IP address of server
  value: {get_attr: [server_floating_ip, ip]}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM