How to get details from PyYAML exception?

wallyk picture wallyk · May 16, 2015 · Viewed 8.8k times · Source

I want to gracefully notify the user exactly where their mucked up YAML file is flawed. Line 288 of python-3.4.1/lib/python-3.4/yaml/scanner.py is where it reports a common parsing error and handles it by throwing an exception:

raise ScannerError("while scanning a simple key", key.mark,
                   "could not found expected ':'", self.get_mark())

I am struggling how to report it.

try:
    parsed_yaml = yaml.safe_load(txt)

except yaml.YAMLError as exc:
    print ("scanner error 1")
    if hasattr(exc, 'problem_mark'):
        mark = exc.problem_mark
        print("Error parsing Yaml file at line %s, column %s." %
                                            (mark.line, mark.column+1))
    else:
        print ("Something went wrong while parsing yaml file")
    return

This gives

$ yaml_parse.py
scanner error 1
Error parsing Yaml file line 1508, column 9.

But how do I get the error text and whatever is in key.mark and the other mark?

More usefully, how do I examine the PyYaml source to figure this out? The ScannerError class seems to ignore the parameters (from scanner.py line 32):

class ScannerError(MarkedYAMLError):
     pass

Answer

wallyk picture wallyk · May 23, 2015

Based on @Anthon's answer, this code works quite well:

try:
    import yaml
except:
    print ('Fatal error:  Yaml library not available')
    quit()

f = open ('y.yml')
txt = f.read()

try:
    yml = yaml.load(txt, yaml.SafeLoader)

except yaml.YAMLError as exc:
    print ("Error while parsing YAML file:")
    if hasattr(exc, 'problem_mark'):
        if exc.context != None:
            print ('  parser says\n' + str(exc.problem_mark) + '\n  ' +
                str(exc.problem) + ' ' + str(exc.context) +
                '\nPlease correct data and retry.')
        else:
            print ('  parser says\n' + str(exc.problem_mark) + '\n  ' +
                str(exc.problem) + '\nPlease correct data and retry.')
    else:
        print ("Something went wrong while parsing yaml file")
    return

# make use of `yml`

Example outputs with mildly clobbered data:

$ yaml_parse.py
Error while parsing YAML file:
  parser says
  in "<unicode string>", line 1525, column 9:
      - name: Curve 1
            ^
  could not found expected ':' while scanning a simple key
Please correct data and retry.

$ yaml_parse.py
Error while parsing YAML file:
  parser says
  in "<unicode string>", line 1526, column 10:
        curve: title 1
             ^
  mapping values are not allowed here
Please correct data and retry.