Anoop P Alias Anoop P Alias - 1 month ago 15
Python Question

PyYAML dumping boolean

I am loading a yaml True/False item(example below) from a YAML file.

gzip: False


This is correctly interpreted in a Jinja2 template as boolean True.

The same YAML file is being read by another script, passed over as a python CGI form data and eventually written to the YAML file using

with open(myyaml, 'w') as yaml_file:
yaml_file.write(yaml.dump(dict, default_flow_style=False))


The issue is that this then writes the True/False with a single quote

gzip: 'False'


which causes the jinja2 template to not interpret the value as boolean and always sets value as true in

{{ if gzip }}


Is there a way to dump the YAML file with True/False values that are treated as boolean ( I mean without the quotes ).

Answer

.dump() just dumps the data that it gets and it must have gotten a string instead of boolean as value for the key gzip. Since that string value, if dumped unquoted can be misinterpreted as a boolean it gets quoted.

Since you get your material from a CGI form any value True or False will be a string. Before dumping your data, you explicitly have to convert these values you got from CGI to booleans.

You can walk over your dictionary and do something generic processing before you dump:

import sys
import yaml

# simulating getting string type values from CGI
data = dict(gzip='False', intval="1", strval="abc") 

for k in data:
    v = data[k]
    try:
        v = int(v)
        data[k] = v
    except ValueError:
        vl = v.lower()
        if vl == 'false':
            data[k] = False
        elif vl == 'true':
            data[k] = True

yaml.safe_dump(data, sys.stdout, default_flow_style=False)

gives:

gzip: false
intval: 1
strval: abc

Please note that abc is not quoted, because it cannot be interpreted as anything else but a string. The above of course also converts strings 'True' or 'False' that would have to stay strings. If that is not what you want, you have to select conversion based on the key.

There are two other major problems with your two lines of Python:

with open(myyaml, 'w') as yaml_file:
    yaml_file.write(yaml.dump(dict, default_flow_style=False)) 
  1. You should never use a Python keyword (dict) as a variable name, that is just asking for trouble later on in your code.
  2. yaml.dump() dumps data to a stream. It has a facility that if you don't specify the stream where things have to go to, the output is written to an internal stream object, from which the final value is returned. You should not abuse this, to then write this returned value to the yaml_file. Instead do:

    with open(myyaml, 'w') as yaml_file:
        yaml.dump(dict, yaml_file, default_flow_style=False))
    

    Your way is inefficient (apart from showing lack of understanding).

Comments