其他分享
首页 > 其他分享> > 如何从PyYAML异常中获取详细信息?

如何从PyYAML异常中获取详细信息?

作者:互联网

我想优雅地通知用户他们的混乱YAML文件存在缺陷. python-3.4.1 / lib / python-3.4 / yaml / scanner.py.28的第288行报告了一个常见的解析错误,并通过抛出异常来处理它:

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

我正在努力报道它.

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

这给了

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

但是如何获取错误文本以及key.mark和另一个标记中的内容?

更有用的是,我如何检查PyYaml源来解决这个问题? ScannerError类似乎忽略了参数(来自scanner.py第32行):

class ScannerError(MarkedYAMLError):
     pass

解决方法:

ScannerError类没有定义任何方法(pass语句的工作方式与no-op类似.这使得它的功能与基类MarkedYAMLError相同,而且是存储数据的那个.来自error.py:

class MarkedYAMLError(YAMLError):
    def __init__(self, context=None, context_mark=None,
                 problem=None, problem_mark=None, note=None):
        self.context = context
        self.context_mark = context_mark
        self.problem = problem
        self.problem_mark = problem_mark
        self.note = note

    def __str__(self):
        lines = []
        if self.context is not None:
            lines.append(self.context)
        if self.context_mark is not None  \
           and (self.problem is None or self.problem_mark is None
                or self.context_mark.name != self.problem_mark.name
                or self.context_mark.line != self.problem_mark.line
                or self.context_mark.column != self.problem_mark.column):
            lines.append(str(self.context_mark))
        if self.problem is not None:
            lines.append(self.problem)
        if self.problem_mark is not None:
            lines.append(str(self.problem_mark))
        if self.note is not None:
            lines.append(self.note)
        return '\n'.join(lines)

如果你从文件txt.yaml开始:

hallo: 1
bye

和test.py:

import ruamel.yaml as yaml
txt = open('txt.yaml')
data = yaml.load(txt, yaml.SafeLoader)

你会得到不那么描述性的错误:

...
ruamel.yaml.scanner.ScannerError: while scanning a simple key
  in "txt.yaml", line 2, column 1
could not find expected ':'
  in "txt.yaml", line 3, column 1

但是,如果您更改test.py的第二行:

import ruamel.yaml as yaml
txt = open('txt.yaml').read()
data = yaml.load(txt, yaml.SafeLoader)

你会得到更有趣的错误描述:

...
ruamel.yaml.scanner.ScannerError: while scanning a simple key
  in "<byte string>", line 2, column 1:
    bye
    ^
could not find expected ':'
  in "<byte string>", line 3, column 1:

    ^

这种差异是因为get_mark()(在reader.py中)有更多的上下文指向它是否处理流:

def get_mark(self):
    if self.stream is None:
        return Mark(self.name, self.index, self.line, self.column,
                    self.buffer, self.pointer)
    else:
        return Mark(self.name, self.index, self.line, self.column,
                    None, None)

此数据将进入context_mark属性.当您想要为错误提供更多上下文时,请查看它.但是如上所示,只有从缓冲区而不是流中解析YAML输入时才有效.

搜索YAML源是一项艰巨的任务,各种类的所有方法都附加到Loader或Dumper,它们是父类.最好的帮助
跟踪这是在def method_name上使用grep(因为至少方法名称都是独特的(因为它们必须为此起作用).

在上面我使用了我的增强版PyYAML,名为ruamel.yaml,为了这个答案的目的,他们应该工作相同.

标签:python,exception-handling,pyyaml
来源: https://codeday.me/bug/20190612/1222684.html