python inspect.getsource获取错误的源代码

时间:2014-04-26 04:03:16

标签: python introspection inspect

运行此文件foo.py

import inspect

class Parent(object):
    def source1(self):
        class A(object):
            def foo(self):
                pass
        print inspect.getsource(A)
    def source2(self):
        class A(object):
            def bar(self, a, b, c):
                pass
        print inspect.getsource(A)


parent = Parent()
parent.source1()
parent.source2()

生成此输出:

    class A(object):
        def foo(self):
            pass

    class A(object):
        def foo(self):
            pass

当我希望它产生这个输出时:

    class A(object):
        def foo(self):
            pass

    class A(object):
        def bar(self, a, b, c):
            pass

我在测试中遇到了这个问题。我在测试方法的主体中重用名称AB作为类名。我正在测试一个依赖于inspect.getsource的函数,而且......它不起作用,因为后来的测试是从前面提到的A和{{1}开始的。 } class。

2 个答案:

答案 0 :(得分:1)

inspect.getsource调用实际上解析了源文件,查找了类定义,并返回了它在缩进的最低级别找到的第一个它正在寻找的名称。换句话说,它不会做你要求它做的事情。

这是一种略有不同的方法,可以产生您正在寻找的输出,并且可能会满足您的需求:

import inspect

class Parent(object):
    def source1(self):
        class A1(object):
            def foo(self):
                pass
        A = A1
        print inspect.getsource(A)
    def source2(self):
        class A2(object):
            def bar(self, a, b, c):
                pass
        A = A2
        print inspect.getsource(A)


parent = Parent()
parent.source1()
parent.source2()

类定义仍然可以通过您想要的名称引用(例如" A"),但源代码中的实际定义使用不同的名称,因此getsource可以找到它。

答案 1 :(得分:1)

这是因为inspect.getsource在源文件中找到第一个匹配的class A。根据Python 2.7.6的545 line中的inspect.py,此模式用于查找源。

pat = re.compile(r'^(\s*)class\s*' + name + r'\b')

因此,如果您首先在代码前面定义class A

import inspect

class A(object):
    pass

class Parent(object):
    def source1(self):
        class A(object):
            def foo(self):
                pass
        print 'id of A in source1 :', id(A)
        print inspect.getsource(A)
    def source2(self):
        class A(object):
            def bar(self, a, b, c):
                pass
        print 'id of A in source2 :', id(A)
        print inspect.getsource(A)

print 'id of A in global :', id(A)
parent = Parent()
parent.source1()
parent.source2()

结果将是

id of A in global : 12512848
id of A in source1 : 12415088
class A(object):
    pass

id of A in source2 : 12356672
class A(object):
    pass

即使他们的对象id不同。