1

I want to dump a dict to a yaml file without the surrounding quotes. Basically like a mapping

import yaml

windows_list = []
server_list = ['abc-def-01', 'pqr-str-02']
site_list = ['dev', 'prod']

server_dict = dict(zip(server_list, site_list))

for k,v in server_dict.items():
    a = '{ SERVER: '+k+', SITE: '+v+' }'
    windows_list.append(a)

final_dict = {'service':'something','servers': windows_list}

with open('config.yml', 'w') as yaml_file:
    yaml.dump(final_dict, yaml_file, default_flow_style=False)

The output of config.yml is below:

service: some name
servers:
- '{ SERVER: abc-def-01, SITE: dev }'
- '{ SERVER: pqr-str-02, SITE: prod }'

I do not want the quotes around it. I want it to be a mapping without the quotes

Desired output

service: some name
servers:
- { SERVER: abc-def-01, SITE: dev }
- { SERVER: pqr-str-02, SITE: prod }

I read this post and it says its not possible to remove quotes if you have special characters, but I want to know if there is a workaround of some sort to achieve what I want.

Anthon
  • 59,987
  • 25
  • 170
  • 228
Bharath
  • 519
  • 8
  • 22

3 Answers3

1

Try this:

for k,v in server_dict.items():
    a = { 'SERVER': f'{k}', 'SITE': f'{v}' }
    windows_list.append(a)

final_dict = {'service':'something','servers': windows_list}

with open('config.yml', 'w') as yaml_file:
    yaml.dump(final_dict, yaml_file, default_flow_style=False)

It will produce exactly what you need in yaml format/structure:

servers:
- SERVER: abc-def-01
  SITE: dev
- SERVER: pqr-str-02
  SITE: prod
service: something

HTH

Danail Petrov
  • 1,860
  • 9
  • 11
  • Thanks for your answer! I needed the YAML to be exactly as seen in the desired output. Anthon's answer works better for my situation. – Bharath Jul 27 '20 at 23:42
1

If you want to output a dict, don't construct a string. Construct a dict instead:

import yaml

windows_list = []
server_list = ['abc-def-01', 'pqr-str-02']
site_list = ['dev', 'prod']

server_dict = dict(zip(server_list, site_list))

for k,v in server_dict.items():
    windows_list.append({'SERVER': k, 'SITE': v})

final_dict = {'service':'something','servers': windows_list}

with open('config.yml', 'w') as yaml_file:
    yaml.dump(final_dict, yaml_file, default_flow_style=False)

This will output

servers:
- SERVER: abc-def-01
  SITE: dev
- SERVER: pqr-str-02
  SITE: prod
service: something

If you want the items be represented in flow style, you can use a custom representer:

import yaml

windows_list = []
server_list = ['abc-def-01', 'pqr-str-02']
site_list = ['dev', 'prod']

class ServerMap:
    def __init__(self, server, site):
        self.server = server
        self.site = site

def servermap_representer(dumper, data):
    return dumper.represent_mapping('tag:yaml.org,2002:map',
            {'SERVER': data.server, 'SITE': data.site}, [True, True])

yaml.add_representer(ServerMap, servermap_representer)

server_dict = dict(zip(server_list, site_list))

for k,v in server_dict.items():
    windows_list.append(ServerMap(k, v))

final_dict = {'service':'something','servers': windows_list}

with open('config.yml', 'w') as yaml_file:
    yaml.dump(final_dict, yaml_file, default_flow_style=False)

Output:

servers:
- {SERVER: abc-def-01, SITE: dev}
- {SERVER: pqr-str-02, SITE: prod}
service: something
flyx
  • 29,987
  • 6
  • 79
  • 110
  • Thanks @flyx. Tried and it works, but I have accepted Anthon's answer as it doesn't change the order of the values. – Bharath Jul 27 '20 at 23:38
0

The quotes are needed because the strings you create and dump, look like a flow-style mapping. In other words when you load what you desire you get a different data-structure than what you created "by hand" (or would load from the output you get).

If you are stuck with such a situation, the best thing to do is load what you want to get and dump the Python datastructure so you know what need to create. That also verifies if what you want is actually YAML:

import sys
import ruamel.yaml

yaml_str = """\
service: some name
servers:
- { SERVER: abc-def-01, SITE: dev }
- { SERVER: pqr-str-02, SITE: prod }
"""

yaml = ruamel.yaml.YAML(typ='safe')
data = yaml.load(yaml_str)
print(data)

which gives:

{'service': 'some name', 'servers': [{'SERVER': 'abc-def-01', 'SITE': 'dev'}, {'SERVER': 'pqr-str-02', 'SITE': 'prod'}]}

As you can see the sequence consists of dictionaries, so that is what you need to append:

import sys
import ruamel.yaml


windows_list = []
server_list = ['abc-def-01', 'pqr-str-02']
site_list = ['dev', 'prod']

server_dict = dict(zip(server_list, site_list))

for k,v in server_dict.items():
    a = { 'SERVER': k, 'SITE': v }
    windows_list.append(a)

final_dict = {'service':'something', 'servers': windows_list}

yaml = ruamel.yaml.YAML()
yaml.default_flow_style = None
yaml.dump(final_dict, sys.stdout)

Which results in:

service: something
servers:
- {SERVER: abc-def-01, SITE: dev}
- {SERVER: pqr-str-02, SITE: prod}

BTW. The recommended extension for YAML files has been .yaml since September 2006.

Anthon
  • 59,987
  • 25
  • 170
  • 228