首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Python ast to dot图

Python ast to dot图
EN

Stack Overflow用户
提问于 2011-12-01 19:23:56
回答 2查看 2.9K关注 0票数 10

我正在分析python代码生成的抽象语法树以获取“乐趣和利润”,我希望有比"ast.dump“更图形化的东西来实际查看生成的抽象语法树。

从理论上讲,它已经是一棵树了,所以创建一个图应该不是太难,但我不明白我怎么能做到。

ast.walk似乎采用了BFS策略,而visitX方法我看不到父级,或者我似乎找不到创建图形的方法……

似乎唯一的方法就是编写我自己的DFS遍历函数,这样做有意义吗?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2011-12-01 20:25:03

如果你看看ast.NodeVisitor,你会发现它是一个相当普通的类。您可以将其子类化,也可以根据需要重新实现它的遍历策略。例如,在访问节点时保留对父节点的引用非常简单,只需添加一个也接受父节点作为参数的visit方法,并从您自己的generic_visit传递该方法即可。

顺便说一句,看起来NodeVisitor.generic_visit实现了DFS,所以你所要做的就是添加父节点传递。

票数 6
EN

Stack Overflow用户

发布于 2011-12-01 21:49:30

太棒了,它很有效,而且非常简单

代码语言:javascript
复制
class AstGraphGenerator(object):

    def __init__(self):
        self.graph = defaultdict(lambda: [])

    def __str__(self):
        return str(self.graph)

    def visit(self, node):
        """Visit a node."""
        method = 'visit_' + node.__class__.__name__
        visitor = getattr(self, method, self.generic_visit)
        return visitor(node)

    def generic_visit(self, node):
        """Called if no explicit visitor function exists for a node."""
        for _, value in ast.iter_fields(node):
            if isinstance(value, list):
                for item in value:
                    if isinstance(item, ast.AST):
                        self.visit(item)

            elif isinstance(value, ast.AST):
                self.graph[type(node)].append(type(value))
                self.visit(value)

所以它和普通的NodeVisitor一样,但是我有一个默认的字典,我为每个子节点添加了节点的类型。然后我把这个字典传递给pygraphviz.AGraph,我得到了很好的结果。

唯一的问题是该类型不能表达太多信息,但是另一方面,使用ast.dump()太过冗长。

最好的办法是获得每个节点的实际源代码,这是可能的吗?

编辑:现在好多了,我传入了构造函数和源代码,如果可能的话,我试着得到代码行,否则就打印出类型。

代码语言:javascript
复制
class AstGraphGenerator(object):

    def __init__(self, source):
        self.graph = defaultdict(lambda: [])
        self.source = source  # lines of the source code

    def __str__(self):
        return str(self.graph)

    def _getid(self, node):
        try:
            lineno = node.lineno - 1
            return "%s: %s" % (type(node), self.source[lineno].strip())

        except AttributeError:
            return type(node)

    def visit(self, node):
        """Visit a node."""
        method = 'visit_' + node.__class__.__name__
        visitor = getattr(self, method, self.generic_visit)
        return visitor(node)

    def generic_visit(self, node):
        """Called if no explicit visitor function exists for a node."""
        for _, value in ast.iter_fields(node):
            if isinstance(value, list):
                for item in value:
                    if isinstance(item, ast.AST):
                        self.visit(item)

            elif isinstance(value, ast.AST):
                node_source = self._getid(node)
                value_source = self._getid(value)
                self.graph[node_source].append(value_source)
                # self.graph[type(node)].append(type(value))
                self.visit(value)
票数 7
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/8340567

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档