parser.md
1> **Источник:** https://python-all.ru/3.9/library/parser.html2>3> «Документация Python на русском» – неофициальный перевод официальной документации Python: версии от 2.6 до 3.16, полнотекстовый поиск, английский оригинал рядом с переводом. Эта Markdown-версия страницы предназначена для работы с LLM: вставьте её в ChatGPT, Claude или Cursor.45---67# [`parser`](https://python-all.ru/3.9/library/parser.html#module-parser) – Доступ к деревьям разбора Python89---1011Модуль [`parser`](https://python-all.ru/3.9/library/parser.html#module-parser) предоставляет интерфейс к внутреннему синтаксическому анализатору Python и компилятору байт-кода. Основное назначение этого интерфейса – дать возможность Python-коду редактировать дерево разбора выражения Python и создавать из него исполняемый код. Это лучше, чем пытаться разобрать и изменить произвольный фрагмент кода как строку, поскольку разбор выполняется точно так же, как и для самого кода приложения. Кроме того, это быстрее.1213> **Предупреждение**14>15> Модуль parser устарел и будет удалён в будущих версиях Python. В большинстве случаев можно использовать этап генерации и компиляции абстрактного синтаксического дерева (AST) с помощью модуля [`ast`](https://python-all.ru/3.9/library/ast.html#module-ast).1617Следует отметить несколько моментов, важных для использования создаваемых структур данных. Это не учебник по редактированию деревьев разбора для кода Python, но здесь приведены некоторые примеры использования модуля [`parser`](https://python-all.ru/3.9/library/parser.html#module-parser).1819Прежде всего необходимо хорошо понимать грамматику Python, обрабатываемую внутренним парсером. Полную информацию о синтаксисе языка см. в [Справочнике по языку Python](https://python-all.ru/3.9/reference/index.html#reference-index). Сам синтаксический анализатор создаётся на основе спецификации грамматики, определённой в файле `Grammar/Grammar` в стандартной поставке Python. Деревья разбора, хранящиеся в ST-объектах, создаваемых этим модулем, являются фактическим результатом работы внутреннего парсера при вызове функций [`expr()`](https://python-all.ru/3.9/library/parser.html#parser.expr) или [`suite()`](https://python-all.ru/3.9/library/parser.html#parser.suite) (описаны ниже). ST-объекты, созданные функцией [`sequence2st()`](https://python-all.ru/3.9/library/parser.html#parser.sequence2st), точно имитируют эти структуры. Имейте в виду, что значения последовательностей, считающиеся «корректными», меняются от версии Python к версии по мере пересмотра формальной грамматики языка. Однако перенос кода из одной версии Python в другую в виде исходного текста всегда позволяет создать корректные деревья разбора в целевой версии, с единственным ограничением: переход на более старую версию интерпретатора не поддерживает более новые языковые конструкции. Деревья разбора обычно несовместимы между версиями, хотя исходный код обычно был совместим вперёд в пределах одной основной серии.2021Каждый элемент последовательностей, возвращаемых функциями [`st2list()`](https://python-all.ru/3.9/library/parser.html#parser.st2list) или [`st2tuple()`](https://python-all.ru/3.9/library/parser.html#parser.st2tuple), имеет простую форму. Последовательности, представляющие нетерминальные элементы грамматики, всегда имеют длину больше единицы. Первый элемент – целое число, идентифицирующее продукцию грамматики. Этим числам присвоены символические имена в заголовочном файле C `Include/graminit.h` и в модуле Python [`symbol`](https://python-all.ru/3.9/library/symbol.html#module-symbol). Каждый следующий элемент последовательности представляет компонент продукции, распознанный во входной строке; это всегда последовательности той же формы, что и родительская. Важная особенность этой структуры: ключевые слова, используемые для идентификации типа родительского узла (например, ключевое слово [`if`](https://python-all.ru/3.9/reference/compound_stmts.html#if) в `if_stmt`), включаются в дерево узлов без какой-либо специальной обработки. Например, ключевое слово `if` представляется кортежем `(1, 'if')`, где `1` – числовое значение, связанное со всеми токенами `NAME`, включая имена переменных и функций, определённые пользователем. В альтернативной форме, возвращаемой при запросе информации о номере строки, тот же токен может быть представлен как `(1, 'if', 12)`, где `12` – номер строки, в которой был найден терминальный символ.2223Терминальные элементы представляются почти так же, но без дочерних элементов и с добавлением исходного текста, который был распознан. Пример ключевого слова [`if`](https://python-all.ru/3.9/reference/compound_stmts.html#if) выше является показательным. Различные типы терминальных символов определены в заголовочном файле C `Include/token.h` и модуле Python [`token`](https://python-all.ru/3.9/library/token.html#module-token).2425ST-объекты не обязательны для поддержки функциональности этого модуля, но предоставляются для трёх целей: позволить приложению распределить затраты на обработку сложных деревьев разбора, предоставить представление дерева разбора, экономящее память по сравнению с представлением в виде списков или кортежей Python, и облегчить создание дополнительных модулей на C, работающих с деревьями разбора. В Python можно создать простой класс-«обёртку», чтобы скрыть использование ST-объектов.2627Модуль [`parser`](https://python-all.ru/3.9/library/parser.html#module-parser) определяет функции для нескольких различных целей. Наиболее важные – создание ST-объектов и преобразование ST-объектов в другие представления, такие как деревья разбора и скомпилированные объекты кода; также есть функции для запроса типа дерева разбора, представленного ST-объектом.2829> **См. также**30>31> **Модуль [`symbol`](https://python-all.ru/3.9/library/symbol.html#module-symbol)**32>33> Полезные константы, представляющие внутренние узлы дерева разбора.34>35> **Модуль [`token`](https://python-all.ru/3.9/library/token.html#module-token)**36>37> Полезные константы, представляющие листовые узлы дерева разбора, и функции для проверки значений узлов.3839## Создание ST-объектов4041ST-объекты могут быть созданы из исходного кода или из дерева разбора. При создании ST-объекта из исходного кода используются разные функции для создания форм `'eval'` и `'exec'`.4243#### `parser.expr(source)`4445Функция [`expr()`](https://python-all.ru/3.9/library/parser.html#parser.expr) анализирует параметр *source* так, как если бы он был входными данными для `compile(source, 'file.py', 'eval')`. В случае успешного разбора создаётся ST-объект для хранения внутреннего представления дерева разбора, в противном случае возбуждается соответствующее исключение.4647#### `parser.suite(source)`4849Функция [`suite()`](https://python-all.ru/3.9/library/parser.html#parser.suite) анализирует параметр *source* так, как если бы он был входными данными для `compile(source, 'file.py', 'exec')`. В случае успешного разбора создаётся ST-объект для хранения внутреннего представления дерева разбора, в противном случае возбуждается соответствующее исключение.5051#### `parser.sequence2st(sequence)`5253Эта функция принимает дерево разбора, представленное в виде последовательности, и, если возможно, строит внутреннее представление. Если удаётся проверить, что дерево соответствует грамматике Python и все узлы являются допустимыми типами узлов в текущей версии Python, из внутреннего представления создаётся ST-объект и возвращается вызывающему. Если при создании внутреннего представления возникла проблема или дерево не прошло проверку, возбуждается исключение [`ParserError`](https://python-all.ru/3.9/library/parser.html#parser.ParserError). Не следует предполагать, что ST-объект, созданный таким образом, скомпилируется корректно; обычные исключения, возбуждаемые при компиляции, могут возникнуть при передаче ST-объекта функции [`compilest()`](https://python-all.ru/3.9/library/parser.html#parser.compilest). Это может указывать на проблемы, не связанные с синтаксисом (например, исключение [`MemoryError`](https://python-all.ru/3.9/library/exceptions.html#MemoryError)), но также может быть связано с конструкциями вроде результата разбора `del f(0)`, который ускользает от парсера Python, но проверяется компилятором байт-кода.5455Последовательности, представляющие терминальные токены, могут быть представлены либо двухэлементными списками вида `(1, 'name')`, либо трёхэлементными списками вида `(1, 'name', 56)`. Если присутствует третий элемент, он считается допустимым номером строки. Номер строки может быть указан для любого подмножества терминальных символов во входном дереве.5657#### `parser.tuple2st(sequence)`5859Это та же функция, что и [`sequence2st()`](https://python-all.ru/3.9/library/parser.html#parser.sequence2st). Данная точка входа сохраняется для обратной совместимости.6061## Преобразование ST-объектов6263ST-объекты, независимо от входных данных, использованных для их создания, могут быть преобразованы в деревья разбора, представленные в виде списков или кортежей, или скомпилированы в исполняемые объекты кода. Деревья разбора могут быть извлечены с информацией о номерах строк или без неё.6465#### `parser.st2list(st, line_info=False, col_info=False)`6667Эта функция принимает ST-объект от вызывающего в параметре *st* и возвращает список Python, представляющий эквивалентное дерево разбора. Полученное представление в виде списка можно использовать для просмотра или создания нового дерева разбора в форме списка. Эта функция не вызывает ошибок, если достаточно памяти для построения представления в виде списка. Если дерево разбора будет использоваться только для просмотра, следует использовать [`st2tuple()`](https://python-all.ru/3.9/library/parser.html#parser.st2tuple), чтобы уменьшить потребление памяти и фрагментацию. Когда требуется представление в виде списка, эта функция значительно быстрее, чем получение представления в виде кортежа и последующее преобразование его во вложенные списки.6869Если *line\_info* равен true, для всех терминальных токенов будет включена информация о номере строки в качестве третьего элемента списка, представляющего токен. Обратите внимание, что указанный номер строки определяет строку, в которой токен *заканчивается*. Эта информация опускается, если флаг равен false или опущен.7071#### `parser.st2tuple(st, line_info=False, col_info=False)`7273Эта функция принимает ST-объект от вызывающего в параметре *st* и возвращает кортеж Python, представляющий эквивалентное дерево разбора. За исключением возврата кортежа вместо списка, эта функция идентична [`st2list()`](https://python-all.ru/3.9/library/parser.html#parser.st2list).7475Если *line\_info* равен true, для всех терминальных токенов будет включена информация о номере строки в качестве третьего элемента списка, представляющего токен. Эта информация опускается, если флаг равен false или опущен.7677#### `parser.compilest(st, filename='<syntax-tree>')`7879Байт-компилятор Python можно вызвать для объекта ST, чтобы получить объекты кода, которые можно использовать как часть вызова встроенных функций [`exec()`](https://python-all.ru/3.9/library/functions.html#exec) или [`eval()`](https://python-all.ru/3.9/library/functions.html#eval). Эта функция предоставляет интерфейс к компилятору, передавая внутреннее синтаксическое дерево из *st* парсеру, используя имя исходного файла, заданное параметром *filename*. Значение по умолчанию, указанное для *filename*, указывает, что источником был объект ST.8081Компиляция объекта ST может привести к исключениям, связанным с компиляцией; примером может служить [`SyntaxError`](https://python-all.ru/3.9/library/exceptions.html#SyntaxError), вызванное синтаксическим деревом для `del f(0)`: этот оператор считается допустимым в формальной грамматике Python, но не является допустимой языковой конструкцией. [`SyntaxError`](https://python-all.ru/3.9/library/exceptions.html#SyntaxError), возбуждаемое для такой ситуации, на самом деле обычно генерируется байт-компилятором Python, поэтому оно может быть возбуждено на этом этапе модулем [`parser`](https://python-all.ru/3.9/library/parser.html#module-parser). Большинство причин сбоя компиляции можно диагностировать программно, проверив синтаксическое дерево.8283## Запросы к объектам ST8485Предоставляются две функции, которые позволяют приложению определить, был ли ST создан как выражение или как блок. Ни одна из этих функций не может быть использована для определения того, был ли ST создан из исходного кода через [`expr()`](https://python-all.ru/3.9/library/parser.html#parser.expr) или [`suite()`](https://python-all.ru/3.9/library/parser.html#parser.suite), или из синтаксического дерева через [`sequence2st()`](https://python-all.ru/3.9/library/parser.html#parser.sequence2st).8687#### `parser.isexpr(st)`8889Когда *st* представляет форму `'eval'`, эта функция возвращает `True`, иначе возвращает `False`. Это полезно, поскольку объекты кода обычно не могут быть опрошены на предмет этой информации с помощью существующих встроенных функций. Обратите внимание, что объекты кода, созданные функцией [`compilest()`](https://python-all.ru/3.9/library/parser.html#parser.compilest), также нельзя так опросить, и они идентичны тем, что создаются встроенной функцией [`compile()`](https://python-all.ru/3.9/library/functions.html#compile).9091#### `parser.issuite(st)`9293Эта функция аналогична [`isexpr()`](https://python-all.ru/3.9/library/parser.html#parser.isexpr) в том, что она сообщает, представляет ли объект ST форму `'exec'`, обычно называемую "блоком". Небезопасно предполагать, что эта функция эквивалентна `not isexpr(st)`, так как в будущем могут поддерживаться дополнительные синтаксические фрагменты.9495## Исключения и обработка ошибок9697Модуль parser определяет одно исключение, но также может передавать другие встроенные исключения из других частей среды выполнения Python. Информацию об исключениях, которые может вызывать каждая функция, смотрите в её описании.9899#### `exception parser.ParserError`100101Исключение, возбуждаемое при сбое в модуле parser. Обычно оно возникает из-за ошибок валидации, а не из-за встроенного исключения [`SyntaxError`](https://python-all.ru/3.9/library/exceptions.html#SyntaxError), возбуждаемого при обычном разборе. Аргумент исключения – либо строка, описывающая причину сбоя, либо кортеж, содержащий последовательность, вызвавшую сбой (из синтаксического дерева, переданного в [`sequence2st()`](https://python-all.ru/3.9/library/parser.html#parser.sequence2st)), и пояснительную строку. Вызовы [`sequence2st()`](https://python-all.ru/3.9/library/parser.html#parser.sequence2st) должны уметь обрабатывать оба типа исключений, в то время как вызовы других функций модуля должны быть готовы только к простым строковым значениям.102103Обратите внимание, что функции [`compilest()`](https://python-all.ru/3.9/library/parser.html#parser.compilest), [`expr()`](https://python-all.ru/3.9/library/parser.html#parser.expr) и [`suite()`](https://python-all.ru/3.9/library/parser.html#parser.suite) могут возбуждать исключения, которые обычно возбуждаются в процессе разбора и компиляции. К ним относятся встроенные исключения [`MemoryError`](https://python-all.ru/3.9/library/exceptions.html#MemoryError), [`OverflowError`](https://python-all.ru/3.9/library/exceptions.html#OverflowError), [`SyntaxError`](https://python-all.ru/3.9/library/exceptions.html#SyntaxError) и [`SystemError`](https://python-all.ru/3.9/library/exceptions.html#SystemError). В этих случаях такие исключения несут всю обычную смысловую нагрузку. За подробной информацией обращайтесь к описанию каждой функции.104105## Объекты ST106107Поддерживаются упорядоченные сравнения и сравнения на равенство между объектами ST. Также поддерживается сериализация объектов ST (с помощью модуля [`pickle`](https://python-all.ru/3.9/library/pickle.html#module-pickle)).108109#### `parser.STType`110111Тип объектов, возвращаемых функциями [`expr()`](https://python-all.ru/3.9/library/parser.html#parser.expr), [`suite()`](https://python-all.ru/3.9/library/parser.html#parser.suite) и [`sequence2st()`](https://python-all.ru/3.9/library/parser.html#parser.sequence2st).112113Объекты ST имеют следующие методы:114115#### `ST.compile(filename='<syntax-tree>')`116117То же, что и `compilest(st, filename)`.118119#### `ST.isexpr()`120121То же, что и `isexpr(st)`.122123#### `ST.issuite()`124125То же, что и `issuite(st)`.126127#### `ST.tolist(line_info=False, col_info=False)`128129То же, что и `st2list(st, line_info, col_info)`.130131#### `ST.totuple(line_info=False, col_info=False)`132133То же, что и `st2tuple(st, line_info, col_info)`.134135## Пример: эмуляция [`compile()`](https://python-all.ru/3.9/library/functions.html#compile)136137Хотя между разбором и генерацией байт-кода может выполняться множество полезных операций, самая простая операция – ничего не делать. Для этой цели использование модуля [`parser`](https://python-all.ru/3.9/library/parser.html#module-parser) для создания промежуточной структуры данных эквивалентно коду138139```python140>>> code = compile('a + 5', 'file.py', 'eval')141>>> a = 5142>>> eval(code)14310144```145146Эквивалентная операция с использованием модуля [`parser`](https://python-all.ru/3.9/library/parser.html#module-parser) несколько длиннее и позволяет сохранить промежуточное внутреннее синтаксическое дерево в виде объекта ST:147148```python149>>> import parser150>>> st = parser.expr('a + 5')151>>> code = st.compile('file.py')152>>> a = 5153>>> eval(code)15410155```156157Приложение, которому нужны как объекты ST, так и объекты кода, может упаковать этот код в готовые функции:158159```python160import parser161162def load_suite(source_string):163 st = parser.suite(source_string)164 return st, st.compile()165166def load_expression(source_string):167 st = parser.expr(source_string)168 return st, st.compile()169```170