writing Yaml file in python with no new line

Question:

Let’s say I have the following snippet :

import yaml
Key = ["STAGE0", "STAGE1"]
dict = {}
dict[Key[0]] = [' ']
dict[Key[1]] = [' ']
dict[Key[0]][0]="HEY" 
dict[Key[0]][0]="WHY newline?"
with open("SUMMARY.YAML", "w") as file_yaml:
    yaml.dump(dict, file_yaml)

The output SUMMARY.YAML file looks like this :

STAGE0:
- WHY newline?
STAGE1:
- ' '

However I need to save them, in the following desired format :

STAGE0: WHY newline?
STAGE1: ' '

I am unable to get this output

Asked By: Ayan Mitra

||

Answers:

You’re creating a much more complex structure than you need, full of lists and references, just create the dict directly if you can

data = {
    "STAGE0": "value0",    # single value
    "STAGE1": ["value1"],  # value in list
}
>>> print(yaml.dump(data))
STAGE0: value0
STAGE1:
- value1

or if you’re amending in possible steps, just add the keys and values directly

data = {}

if True:
    data["STAGE0"] = "value0"
if True:
    data["STAGE1"] = "value1"

Finally, if you do create lists, .append() is likely a much better choice to add values rather than trying to create all the indicies initially

try:
    data[key].append(value)
except KeyError:
    data[key] = [value]
Answered By: ti7

There are multiple problems with your program that you should be aware of:

  • dict is a reserved keyword in Python. You should not mask it by using it as a variable name. With that that keyword you can make an empty dictionary data = dict() or
    initialize one, with some restrictions to the keys: data = dict(a=42, hello='world')
  • Your dict[Key[0]] = [' '] set the value of dict['STAGE0'] to a list with one element, the string with one space,
    then dict[Key[0]][0]="HEY" overwrites this string with one space with "HEY" and the following code line
    overwrites that with "WHY newline". You could directly do `dict[Key[0]] = [‘WHY newline?’]

A minor thing to think about is being consistent with using single or double quotes around strings, and not use both (triple quotes can be different, and usually triple double quotes are used)

As for the desired output, that is a YAML document with a root level mapping that consists of keys and values that
are all scalars. Mappings are loaded from YAML as dictionaries (unless tagged in YAML, but you don’t have that). Scalars
are loaded as strings, or if they are recognised as such, as booleans, integers, floats, datetime.datetime, or datetime.date
instances.

You are using PyYAML which I cannot recommend for new developments, as it only supports a subset of YAML 1.1 wich was outdated back in 2009. I recommend using ruamel.yaml in the example (disclaimer: I am the author of that YAML 1.2 library), but the techniques
of getting a solution to your problem are the same.

First load your expected output and inspect the data structure you get loading your desired output. With PyYAML:

import yaml

yaml_str = """
STAGE0: WHY newline?
STAGE1: ' '
"""
    
data = yaml.safe_load(yaml_str)
print(data)

which gives:

{'STAGE0': 'WHY newline?', 'STAGE1': ' '}

Same code using ruamel.yaml:

import ruamel.yaml

yaml_str = """
STAGE0: WHY newline?
STAGE1: ' '
"""
    
yaml = ruamel.yaml.YAML(typ='safe')
data = yaml.load(yaml_str)
print(data)

which also gives:

{'STAGE0': 'WHY newline?', 'STAGE1': ' '}

As you can see the data structure you get consists of a Python dict, with strings as keys and strings as values. There
are no lists, so you should not use them if you start building up the datastructure from scratch. PyYAML:

import sys
import yaml

Key = ['STAGE0', 'STAGE1']

data = {}
data[Key[0]] = 'Why newline?'
data[Key[1]] = ' '
    
with open("SUMMARY.YAML", "w") as file_yaml:
    yaml.dump(data, file_yaml)

print(open('SUMMARY.YAML').read())

which gives your desired output:

STAGE0: Why newline?
STAGE1: ' '

With ruamel.yaml I recommend using a pathlib.Path instance, which gets correctly opened to handle non-ASCII scalars
by default:

import sys
from pathlib import Path
import ruamel.yaml


path = Path('SUMMARY.YAML')
Key = ['STAGE0', 'STAGE1']

data = {}
data[Key[0]] = 'Why newline?'
data[Key[1]] = ' '

yaml = ruamel.yaml.YAML()
yaml.dump(data, path)

print(path.read_text())

giving:

STAGE0: Why newline?
STAGE1: ' '

If you continue to use PyYAML, please be aware that values like 12:34:56 will be loaded as integer (converted
from sexagesimals) and On, Off, Yes, No as booleans although those "features" were written out of
the YAML specfication fourteen years ago.

Answered By: Anthon
Categories: questions Tags: , , , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.