Bob McBobson
Bob McBobson

Reputation: 904

Why can I not parse my simple YAML file without yielding the error "mapping values are not allowed here"?

I am trying to open, parse, then pass my YAML file into a dict in my Python script. However, I can't seem to format the file itself in a simple text editor that will allow it to parsed. I keep getting the error mapping values are not allowed here at the same position within the YAML text file. I have tried to reformat it in various ways, but I keep getting the same error in the same place. My code is set up like so:

from __future__ import print_function
import ruamel.yaml as ry

with open("yamltest2.yaml", 'r') as stream:
    try:
        print(ry.load(stream, Loader= ry.Loader))
    except ry.YAMLError as exc:
        print(exc)

And my YAML text file itself is set up like so (note: my IDE informs me that the error's source always occurs at the end of the line with name:):

input = """\
name: 
    a: 1 # comment
    b: 2
    c: 3
    d: 4
"""

Could anybody help me determine what the root cause for this error?

Upvotes: 0

Views: 683

Answers (2)

Anthon
Anthon

Reputation: 76599

Your IDE might be parsing the full error that you got, ruamel.yaml errors on this with the exact location where your file goes wrong:

mapping values are not allowed here
  in "yamltest2.yaml", line 2, column 5

This is because you start the YAML file with a scalar 'input = """\ name' (the \ here is not an escaping backslash) that spans multiple (two) lines, but then use that scalar as a key in a mapping. That is not allowed in YAML.

If you would want to have that exact a key, you could just specify:

input = """\ name:
    a: 1 # comment
    b: 2
    c: 3
    d: 4

you would have to remove the trailing """ from the file though, as that is an incomplete key without a value, throwing another error.

But this is not what you intended, you probably tried to outsource the embedded YAML string from a program like:

from __future__ import print_function
import ruamel.yaml as ry

input = """\
name: 
    a: 1 # comment
    b: 2
    c: 3
    d: 4
"""

try:
    print(ry.load(input, Loader= ry.Loader))
except ry.YAMLError as exc:
    print(exc)

and while editing copy and pasted all of the deleted lines into your YAML. As @errata already indicated, that is not YAML. If you cannot immediately resolve those issues yourself, you can of course ask here on [so], but a trick that often helps pinpoint what is going wrong is deleting everything starting with the error point and examining what data you load when that the truncated YAML loads without problem. In your case your YAML would need to be truncated to:

input = """\
name

which loads as the string input = """\ name and not as the dict as you expected.

However there is another issues with your code that you should solve: You should not use the standard load(). There is a reason why I raise a warning in ruamel.yaml when you use load() unadorned, as using load() is dangerous. You can get rid of the warning doing load(stream, Loader=ruamel.yaml.Loader) as you do, or suppress the warning with:

import warnings
warnings.simplefilter('ignore', ruamel.yaml.error.UnsafeLoaderWarning)

But I repeat here what I recommend in the warning message ruamel.yaml gives, when called unadorned: use safe_load(). There is no reason for you not to do so:

from __future__ import print_function
import ruamel.yaml as ry

with open("yamltest2.yaml", 'r') as stream:
    try:
        print(ry.safe_load(stream))
    except ry.YAMLError as exc:
        print(exc)

Upvotes: 0

errata
errata

Reputation: 6031

You are mixing Python and YAML in your yamltest2.yaml. Instead of

input = """\
name: 
    a: 1 # comment
    b: 2
    c: 3
    d: 4
"""

your .yaml file should look like:

name: 
    a: 1 # comment
    b: 2
    c: 3
    d: 4

Upvotes: 2

Related Questions