Как игнорировать pyparsing ParseException и продолжить?

Я хотел бы проигнорировать строку в файле, которая не соответствует всем предопределенным парсерам, и продолжить. Строки, которые я хотел бы игнорировать, находятся в широком диапазоне, который я не мог проверить и определить синтаксический анализатор для каждой из них.

Я использую try..except с проходом, когда ParseException пойман. Однако синтаксический анализ немедленно прекращается.

try:
    return parser.parseFile(filename, parse_all)

except ParseException, err:
    msg = 'Error during parsing of {}, line {}'.format(filename, err.lineno)
    msg += '\n' + '-'*70 + '\n'
    msg += err.line + '\n'
    msg += ' '*(err.col-1) + '^\n'
    msg += '-'*70 + '\n' + err.msg
    err.msg = msg

    print(err.msg)
    pass

Я хотел бы продолжить, даже если есть ParseException.

Что вы имеете в виду под the parsing stops immediately.? Вы имеете в виду, что ваша программа завершается чисто? Или возникает другое исключение? Если последнее, опубликуйте новый файл Traceback.

That1Guy 22.04.2019 17:51

Также небольшая придирка: вам не нужно pass в конце вашего блока исключений.

That1Guy 22.04.2019 17:51

@ That1Guy Я хотел бы продолжить синтаксический анализ файла, а не просто изящно выйти с ошибкой исключения.

CarolL 22.04.2019 18:01

Прошу уточнения - что ты имеешь в виду когда вы говорите "парсинг прекращается сразу"? Он останавливается, потому что ваша программа выходит? Или это останавливает из-за другой ошибки? Вы вообще получаете какой-то результат? Вы видите строку в своем операторе печати?

That1Guy 22.04.2019 18:05
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
2
4
418
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Pyparsing на самом деле не имеет опции «продолжить при ошибке», поэтому вам нужно настроить свой синтаксический анализатор так, чтобы он в первую очередь не вызывал ParseException. Что вы можете попробовать, так это добавить в свой синтаксический анализатор что-то вроде | SkipTo(LineEnd())('errors*') в качестве последней уловки. Затем вы можете посмотреть на имя результатов ошибок, чтобы увидеть, какие строки сбились с пути (или добавить действие синтаксического анализа к этому выражению, чтобы захватить больше, чем только текущую строку).

import pyparsing as pp

era = "The" + pp.oneOf("Age Years") + "of" + pp.Word(pp.alphas)

era.runTests("""
    The Age of Enlightenment
    The Years of Darkness
    The Spanish Inquisition
    """)

Отпечатки:

The Age of Enlightenment
['The', 'Age', 'of', 'Enlightenment']

The Years of Darkness
['The', 'Years', 'of', 'Darkness']

The Spanish Inquisition
    ^
FAIL: Expected Age | Years (at char 4), (line:1, col:5)

Добавьте эти строки и снова вызовите runTests:

# added to handle lines that don't match
unexpected = pp.SkipTo(pp.LineEnd(), include=True)("no_one_expects")
era = era | unexpected

Отпечатки:

The Age of Enlightenment
['The', 'Age', 'of', 'Enlightenment']

The Years of Darkness
['The', 'Years', 'of', 'Darkness']

The Spanish Inquisition
['The Spanish Inquisition']
 - no_one_expects: 'The Spanish Inquisition'

Это часто происходит, когда парсер имеет выражение ZeroOrMore или OneOrMore(expressions that might match the empty string), которое в конечном итоге вращается вечно. Попробуйте добавить setDebug() к одному из ваших выражений синтаксического анализатора или добавьте некоторый вывод в действие синтаксического анализа, если оно у вас есть. Кроме того, вам, возможно, придется опубликовать более подробную информацию.

PaulMcG 22.04.2019 19:22

Ха! SkipTo() также должен анализировать LineEnd(), что по умолчанию не выполняется. Добавьте include=True, чтобы получить это. Ответ отредактирован.

PaulMcG 22.04.2019 19:30

Также замените pp.ZeroOrMore(rules) на pp.OneOrMore(rules). Это тоже была ошибка в dictOf, из-за которой синтаксический анализатор вращался вечно. Но вам, возможно, придется опубликовать это как новый вопрос - вашему образцу кода нелегко следовать, и SO не любит длинные темы обсуждения по заданному вопросу.

PaulMcG 22.04.2019 19:33

Спасибо, Пол. Я задал вопрос с более подробной информацией в отдельной теме. stackoverflow.com/q/55798690/11395555

CarolL 22.04.2019 20:06

Другие вопросы по теме