Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
Help us understand the problem. What is going on with this article?

Pythonの抽象構文木をGraphvizで可視化する

More than 1 year has passed since last update.

はじめに

Pythonには抽象構文木を扱うastというモジュールがある。これを使って抽象構文木を可視化してみる。

スクリプト

parse.py
import ast
import sys

from graphviz import Digraph


def visit(node, nodes, pindex, g):
    name = str(type(node).__name__)
    index = len(nodes)
    nodes.append(index)
    g.node(str(index), name)
    if index != pindex:
        g.edge(str(index), str(pindex))
    for n in ast.iter_child_nodes(node):
        visit(n, nodes, index, g)


filename = sys.argv[0]
if len(sys.argv) > 1:
    filename = sys.argv[1]

with open(filename) as f:
    graph = Digraph(format="png")
    tree = ast.parse(f.read())
    visit(tree, [], 0, graph)
    graph.render("test")

実行

例えばこんなファイルを食わせる。

test.py
def func(a, b):
    return a + b


def func2(a):
    print(a)

print("Hello")
$ python parse.py test.py

すると、こんな構文木が得られる。

test.png

ちなみに引数を指定しないと自分自身をパースする。

$ python parse.py

得られる結果はこんな感じ。

test.png

動作原理

基本的にはast.parseで得られた木から再帰的にたどっていくだけ。ast.iter_child_nodes(node)nodeにぶら下がるノードのイテレータが得られるので、それに対してforを回す。

Graphivzのノードのキャプションはtype(node).__name__としたが、そのままg.edgeでつないでしまうと同じ名前が同じノードとみなされてしまうので、一工夫が必要。

そこで、ノードをリストに追加することで、それぞれに一意な通し番号をふる。

    name = str(type(node).__name__)
    index = len(nodes)
    nodes.append(index)
    g.node(str(index), name)

で、この通し番号をGraphvizのノード番号として、繋げば良い。

 g.edge(str(index), str(pindex))

最初は、オブジェクトをリストではなくハッシュに登録してたんだけど、抽象構文オブジェクト、例えばast.Loadはなぜか同じオブジェクトが使い回されているようで、同じノードとみなされてしまう。上記のように一意な通し番号を振れば大丈夫。

kaityo256
記事中に明示されていない場合、私の記事はCC-BY 4.0で、記事に含まれるソースコードはMITライセンスで公開します。
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away