変数名と値の一覧を限定的にソースコードから取り出す
以下、parse_vars.py
# coding: cp932 from compiler import parse, walk, ast class Visitor: def __init__(self, vars_d): self.vars_d = vars_d def visitAssign(self, node): var, val = node.getChildren() if isinstance(var, ast.AssName): if isinstance(val, ast.Const): # a = 1 # b = 1.0 # c = 'str' # に、対応 self.vars_d[var.name] = val.value elif isinstance(val, ast.Name): # def foo(): pass # a = foo # は、対応しない pass elif isinstance(val, ast.CallFunc): # def foo(): return 1 # a = foo() # は、対応しない pass elif isinstance(var, ast.AssTuple): # def bar(): return 1,2 # a,b = bar() # c,d = 3,4 # は、対応しない pass def parse_vars(src): visitor = Visitor({}) walk(parse(src), visitor) return visitor.vars_d
以下、test.py
# coding: cp932 import __main__ import inspect from parse_vars import parse_vars a,z=1,99 b=2 c=1.0 d='string' def foo():pass def bar():return 100,101 e = foo g,h = bar() s=''' def foo2(): aa = 1 def bar2():pass bb = 'bb_val' ''' def baz(): cc = 3 print '-'*20 for var, val in parse_vars(inspect.getsource(__main__)).items(): print var, '=', repr(val) print '-'*20 for var, val in parse_vars(s).items(): print var, '=', repr(val)
以下、実行結果
C:> python test.py -------------------- cc = 3 s = "\ndef foo2():\n aa = 1\n def bar2():pass\n bb = 'bb_val'\n" c = 1.0 b = 2 d = 'string' -------------------- aa = 1 bb = 'bb_val'
構文木を解析して変数名と値を取り出している。ただしすべての場合には対応していないので注意。
関数の定義からコンパイル前の関数のソースコードを取り出す方法はあるのだろうか?foo.func_code.co_codeだとコンパイル後のものなのか何故かうまくいかないし、inspect.getsource(foo)でも取れない。
Visitorクラスのvisit*関数のパターンは、Lib\compilerフォルダのpycodegen.pyとsymbols.pyが参考になった。