написать быстрый парсер в python - PullRequest
8 голосов
/ 27 апреля 2010

Я написал практический рекурсивный анализатор чистого Python для некоторого формата файла ( ARFF ), который мы используем в одной лекции. Сейчас мои упражнения выполняются очень медленно. Оказывается, безусловно, больше всего времени уходит на мой парсер. Это занимает много процессорного времени, HD не является узким местом.

Интересно, какие существуют эффективные способы написания парсера на python? Я бы не стал переписывать его на C. Я пытался использовать jython, но это сильно снижало производительность! Файлы, которые я анализирую, частично огромные (> 150 МБ) с очень длинными строками.

Моему текущему парсеру нужен только предварительный просмотр одного символа. Я бы опубликовал источник здесь, но я не знаю, так ли это хорошая идея. Ведь срок подачи заявок еще не закончился. Но тогда основное внимание в этом упражнении уделяется не анализатору. Вы можете выбрать любой язык, который хотите использовать, и для Java уже есть парсер.

Примечание: у меня есть система x86_64, поэтому psyco (и, похоже, также PyPy) не подходит.

Обновление: теперь я загрузил свой анализатор / модуль записи в bitbucket .

Ответы [ 2 ]

8 голосов
/ 27 апреля 2010

Вы можете использовать ANTLR или pyparsing , они могут ускорить ваш процесс синтаксического анализа.

И если вы хотите сохранить свой текущий код, вы можете посмотреть на Cython / PyPy , который увеличивает вашу производительность (иногда до 4х).

7 голосов
/ 27 апреля 2010

Самый общий совет, который я бы дал без дополнительной информации, состоял бы в том, чтобы прочитать весь файл или, по крайней мере, его значительную часть, сразу в память. Вы не хотите читать по одному символу за раз и искать здесь и там; независимо от буферизации, которая происходит внутри, вероятно, хорошей идеей будет просто сохранить все это в памяти, чтобы вы могли работать с ней так, как вам хочется.

Я написал парсеры на Python, и нет особого требования к ним быть особенно медленнее, чем парсер, написанный на любом другом языке. Как и в случае с такими вещами, более вероятно, что вы делаете работу, которую вам не нужно делать. Из этого класса предметов создание, уничтожение и воссоздание одного и того же объекта обходятся дороже, чем просто его где-то хранить. Повторное вычисление значения снова и снова стоит дороже, чем просто хранить его где-то. И т. Д.

В частности, в Python одна ловушка, в которую попадают люди, делает много ненужных манипуляций со строками. Не добавляйте к строкам по одному символу за раз; когда вы собираете свои токены, выполняйте работу над «главной» строкой и удаляйте токен одним махом. (Другими словами, внесите указатель в строку «master», определите начальную и конечную точки, а затем захватите ее с помощью token = master[start:end].) Объединение строк по одному символу за раз - это короткий путь к снижению производительности. Я подозреваю, что даже если вы хотите / нуждаетесь по какой-то причине в for c in master: newstr += c, вам, возможно, повезет больше, если вы добавите 'c' в список, а затем newstr = ''.join(newstr_charlist).

...