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
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]
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.
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
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]
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 dictionarydata = dict()
or
initialize one, with some restrictions to the keys:data = dict(a=42, hello='world')
- Your
dict[Key[0]] = [' ']
set the value ofdict['STAGE0']
to a list with one element, the string with one space,
thendict[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.