ファンタスティック、それが動作し、それがだから、通常のNodeVisitorと同じだが、私は、私はそれぞれの息子のためにノードの種類を追加しdefaultdictを持って
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)
本当に簡単です。 それから、この辞書をpygraphviz.AGraphに渡して、私は素晴らしい結果を得ました。
唯一の問題は(タイプはあまり言っていないということですが、一方でast.dumpを使用しては)あまりにも冗長です。
各ノードの実際のソースコードを取得するのがベストでしょうか?
EDIT:今、それははるかに良いですが、そうでない場合は、単にタイプをプリントアウトし、私もコンストラクタでソースコードを渡すと、私は可能な場合は、コードの行を取得しよう。
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)
はい、非常に単純な実装ですが、私は最初にすべてのケースをチェックしなければならないと考えましたが、実際にリストであるかどうかを確認しています。たくさん –