user3214546
user3214546

Reputation: 6831

How can I output blank value in python yaml file

I am writing yaml file like this

with open(fname, "w") as f:
     yaml.safe_dump({'allow':'', 'deny': ''}, f,
                    default_flow_style=False, width=50, indent=4)

This outputs:

allow: ''

I want to output as

allow:

How can I do that?

Upvotes: 51

Views: 85478

Answers (4)

Koo
Koo

Reputation: 1709

For None type to be read from python use null in yaml

A YAML file test.yml like this

foo: null
bar: null

will be read by python as

import yaml
test = yaml.load(open('./test.yml'))
print(test)

foo: None
bar: None

Upvotes: 103

Anthon
Anthon

Reputation: 76792

If you load a YAML src

allow:

into Python you get None assigned to the key allow, that is the correct behaviour.

If you use ruamel.yaml (of which I am the author), and its RoundTripDumper, None is written as you want it (which is IMO the most readable, although not explicit):

import ruamel.yaml

print ruamel.yaml.dump(dict(allow=None), Dumper=ruamel.yaml.RoundTripDumper)

will give you:

allow:

You can also properly round-trip this:

import ruamel.yaml

yaml_src = """
allow:
key2: Hello  # some test

"""

data = ruamel.yaml.load(yaml_src, ruamel.yaml.RoundTripLoader)
print('#### 1')
print(data['allow'])
print('#### 2')
print(ruamel.yaml.dump(data, Dumper=ruamel.yaml.RoundTripDumper))

print('#### 3')

print(type(data))

to get as output:

#### 1
None
#### 2
allow:
key2: Hello  # some test


#### 3
<class 'ruamel.yaml.comments.CommentedMap'>

In the above, data is a subclass of ordereddict, which is necessary to keep track of the flowstyle of the input, handling comments attached to lines, order of the keys, etc..
Such a subclass can be created on the fly, but it is normally easier to start with some readable and well formatted YAML code (possible already saved on disc) and then update/extend the values.

Upvotes: 13

Hans Nelsen
Hans Nelsen

Reputation: 377

from yaml import SafeDumper
import yaml

data = {'deny': None, 'allow': None}

SafeDumper.add_representer(
    type(None),
    lambda dumper, value: dumper.represent_scalar(u'tag:yaml.org,2002:null', '')
  )

with open('./yadayada.yaml', 'w') as output:
  yaml.safe_dump(data, output, default_flow_style=False)

There is a way to do this built into python yaml itself. The above code will produce a file containing:

allow:
deny:

Upvotes: 24

sjdenny
sjdenny

Reputation: 831

Using replace, this seems straightforward:

import yaml

fname = 'test.yaml'
with open(fname, "w") as f:
    yaml_str = yaml.safe_dump({'allow':'', 'deny': ''},
                            default_flow_style=False,
                            width=50, 
                            indent=4).replace(r"''", '')
    f.write(yaml_str)

Is there a reason why you want to avoid replace?

There is the drawback that re-loading the yaml file does not reproduce your input:

>>> print yaml.safe_load(open(fname))
{'deny': None, 'allow': None}

Upvotes: 7

Related Questions