【问题标题】:python inspect.getsource gets the wrong sourcepython inspect.getsource 获取错误的源
【发布时间】:2014-04-26 04:03:16
【问题描述】:

运行这个文件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 的函数,而且……它不起作用,因为后来的测试是从早先命名的AB 类中获得的源代码。

【问题讨论】:

    标签: python introspection inspect


    【解决方案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 可以找到它。

    【讨论】:

    • 谢谢。我想我可以阅读inspect 的来源:)
    【解决方案2】:

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

    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 不同。

    【讨论】:

    • 感谢您的回答。你的和上面的都帮助我知道该怎么做。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-11-14
    • 2016-08-26
    • 1970-01-01
    • 1970-01-01
    • 2016-08-24
    • 2016-05-18
    相关资源
    最近更新 更多