Как я могу получить полный AST в Python? - PullRequest
5 голосов
/ 15 июля 2009

Мне нравятся опции, предлагаемые модулем _ast , он действительно мощный. Есть ли способ получить полный AST от него?

Например, если я получу AST следующего кода:

import os
os.listdir(".")

используя:

ast = compile(source_string,"<string>","exec",_ast.PyCF_ONLY_AST)

тело объекта ast будет иметь два элемента: объект import и объект expr . Однако я хотел бы пойти дальше и получить AST import и listdir , другими словами, я бы хотел, чтобы _ast опустился минимально возможный уровень

Я думаю, логично, что такого рода вещи должны быть возможны. Вопрос как ?

РЕДАКТИРОВАТЬ: под самым низким возможным уровнем, я не имел в виду доступ к тому, что "видно". Я хотел бы также получить AST для реализации listdir : например, stat и других вызовов функций, которые могут быть выполнены для него.

Ответы [ 2 ]

8 голосов
/ 15 июля 2009

Вы получаете целое дерево таким образом - вплоть до самого дна - но оно сохраняется как дерево, точно ... поэтому на каждом уровне, чтобы получить дочерние элементы, вы должны явно посетить необходимые атрибуты , Например (я называю compile результат cf, а не ast, потому что это скрыло бы стандартный модуль библиотеки ast - я предполагаю, что у вас только 2,5, а не 2,6, поэтому вы используете нижний -уровень _ast модуль вместо?) ...:

>>> cf.body[0].names[0].name
'os'

Это то, что говорит вам, что оператор импорта импортирует имя os (и это только потому, что 1 - это длина поля .names поля .body[0], которое является import).

В модуле Python 2.6 ast вы также получите помощников, которые позволят вам более легко перемещаться по дереву (например, с помощью шаблона проектирования Visitor), но все дерево присутствует в версии 2.5 (с * 1016). *) или 2.5 (с ast), и в любом случае представляется одинаково.

Для удобного посещения всех узлов дерева в 2.6, используйте модуль ast (без начального подчеркивания) и подкласс ast.NodeVisitor в зависимости от ситуации (или эквивалентно используйте ast.iter_child_nodes рекурсивно и ast.iter_fields при необходимости). Конечно, эти помощники могут быть реализованы на чистом Python поверх _ast, если вы по какой-то причине застряли в 2.5.

5 голосов
/ 15 июля 2009
py> ast._fields
('body',)
py> ast.body
[<_ast.Import object at 0xb7978e8c>, <_ast.Expr object at 0xb7978f0c>]
py> ast.body[1]
<_ast.Expr object at 0xb7978f0c>
py> ast.body[1]._fields
('value',)
py> ast.body[1].value
<_ast.Call object at 0xb7978f2c>
py> ast.body[1].value._fields
('func', 'args', 'keywords', 'starargs', 'kwargs')
py> ast.body[1].value.args
[<_ast.Str object at 0xb7978fac>]
py> ast.body[1].value.args[0]
<_ast.Str object at 0xb7978fac>
py> ast.body[1].value.args[0]._fields
('s',)
py> ast.body[1].value.args[0].s
'.'

НТН

...