Как пропустить документ с ошибками в потоке YAML? - PullRequest
0 голосов
/ 05 августа 2020

Не похоже, что 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
...

Я бы хотел, чтобы код, подобный этому, пропустил плохой документ, но выяснить, "как бы ни был плох этот документ, после ... и --- начинается что-то новое.

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() после моего собственного синтаксического анализа. Но похоже, что это то, что парсер должен делать для меня.

1 Ответ

1 голос
/ 05 августа 2020

Я просто что-то упускаю, и какой-то другой API будет поддерживать это?

Нет, PyYAML не может этого сделать.

Есть ли парсеры в других программах языки поддерживают эту операцию? (если да, то какие)

Мне ничего не известно. Большинство парсеров YAML написаны вручную, некоторые из них являются переводами из PyYAML. Я не знаю ни одной, которая реализует восстановление после ошибок. (Я работал с SnakeYAML, go -yaml, PyYAML, libyaml, YamlDo tNet, и был автором NimYAML и AdaYaml.)

Но похоже, что именно это и должен делать парсер. для меня.

Я думаю, что причины, по которым парсеры не поддерживают это, включают

  • написание совместимого парсера для YAML уже очень сложно без восстановления после ошибок,
  • функция работы с несколькими документами используется редко, поэтому для ее улучшения прилагается мало усилий,
  • это единственный случай, когда очевидно, как реализовать восстановление после ошибок; Я бы сказал, что внутри документа YAML практически невозможно реализовать полезное восстановление после ошибок, и поэтому восстановление после ошибок не рассматривается как очевидная функция для реализации,
  • обходной путь очень прост (вы сами это описали) .
...