如何跳过 YAML 流中有错误的文档?

How do I skip document with errors in YAML stream?

Python 库 pyyaml 似乎不会允许我读取多文档 YAML 流并在解析错误点之后继续。我有两个相关问题:

  1. 我是不是漏掉了什么,其他 API 会支持这个吗?
  2. 其他编程语言的解析器是否支持此操作? (如果有,是哪个)

这是一个多文档 YAML 流的示例:

%YAML 1.1
---
# YAML can contain comments like this
name: David
age: 55
---
name: Mei
age: 50     # Including end-of-line
---
name: Juana: ERROR
age: 47
...
---
name: Adebayo
age: 58
...

我想要类似这样的代码来跳过错误的文档,但要弄清楚“无论这个文档有多糟糕,在 ...---.[=19 之后都会有新的开始=]

with open('data/multidoc-bad.yaml') as stream:
    docs = yaml.load_all(stream)
    while True:
        try:
            doc = next(docs)
            print(doc)
        except StopIteration:
            break
        except Exception as err:
            print(err)

我想得到:

{'name': 'David', 'age': 55}
{'name': 'Mei', 'age': 50}
mapping values are not allowed here
  in "data/multidoc-bad.yaml", line 10, column 12
{'name': 'Adebayo', 'age': 58}

但实际上我听不懂“Adebayo”的最后一行。

我认识到我 可以 自己编写一个小型解析器来读取行并只查找 ...--- 行来分块流。然后在我自己解析后只将单个文档传递给 yaml.loads()。但看起来这确实是解析器应该为我做的。

Am I just missing something, and some other API will support this?

不,PyYAML 不能这样做。

Do parsers in other programming languages support this operation? (if so, which)

None 我知道的。大多数 YAML 解析器都是 hand-written,有相当一部分是从 PyYAML 翻译过来的。我不知道有一个实现错误恢复的。 (我使用 SnakeYAML、go-yaml、PyYAML、libyaml、YamlDotNet,并编写了 NimYAML 和 AdaYaml。)

But it sure seems like that's what a parser is supposed to do for me.

我认为解析器不支持这个的原因包括

  • 如果没有错误恢复,为 YAML 编写兼容的解析器已经非常复杂,
  • multi-document 功能很少使用,因此很少投入精力来增强它,
  • 这是唯一一个很明显如何实现错误恢复的情况;我认为在 YAML 文档中,几乎不可能实现有用的错误恢复,因此错误恢复不被视为一个明显的功能来实现,
  • 解决方法很简单(你自己描述的)。