変数名と値の一覧を限定的にソースコードから取り出す

以下、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が参考になった。