Python如何以编程方式获取类定义的行号

10
假设我有一个名为test.py的模块。 在这个文件中,我知道有一个名为dummy的类。 如何在导入它后获取类dummy定义的行号?
是否有API可以做到这样的事情?
如果dummy是一个函数,那么dummy.__code__.co_firstlineno将返回该函数的行号。但如果dummy是一个类,则没有__code__属性。
我想知道是否有一种方法可以在不解析文件的情况下返回行号。

1
可能是一个XY问题 http://meta.stackexchange.com/questions/66377/what-is-the-xy-problem 你想用它做什么? - kalenpw
你到底想要实现什么,为什么你需要知道行号? - saurabh baid
你不能只解析test.py文件中的class Dummy吗? - Steven Summers
只是好奇,如果dummy是一个函数,那么dummy.__code__.co_firstlineno将返回该行的行号。但如果dummy是一个类,则它没有__code__属性。 - 24April14
类的方法有一个__code__属性,所以您可以通过检查它们中的每一个来粗略地找到行号。 - Steven Summers
3个回答

6

inspect.findsource(test.dummy)[1] 通过在源文件中进行正则搜索来提供行号(速度较慢)。

如果您定义类,可以像这样公开行号:

class MyClass:
    def test_01(self):
        assert 1
    _classline_ = inspect.currentframe().f_code.co_firstlineno
    _thisline_ = inspect.currentframe().f_lineno

2020年更新/Python 3.9+ :inspect.findsource现在使用(缓慢的)ast代替正则表达式。(bpo-35113 / commit 696136b9)


inspect.findsource() 不使用正则表达式来查找类声明。 相反,它实际上会将声明该类的模块完全解析为其抽象语法树(AST)表示形式,然后迭代地搜索该树中声明该类的节点,这是通过标准 ast 模块完成的。好的一面是,这是无错的。坏的一面是,这是如此缓慢和荒谬,以至于您在性能关键代码中永远不应该这样做。ast 模块使基于正则表达式的解析看起来像希腊飞鞋之神赫尔墨斯。 - Cecil Curry
@CecilCurry 最近引入了(慢速)ast使用(bpo-35113 / 696136b9)。已更新。 - kxr

3
看看inspect库的检索源代码部分。试试getsourcefile()getsourcelines()。"最初的回答"

0
这需要我为xdoctest模块编写的静态分析代码。我不确定它是否解决了100%的情况,但我认为它比正则表达式搜索更健壮。
def static_calldefs(modpath):
    from xdoctest import static_analysis as static
    calldefs = dict(static.parse_calldefs(fpath=modpath))
    return calldefs

def get_object_lineno(obj):
    try:
        # functions just 
        lineno = obj.__code__.co_firstlineno
    except AttributeError:
        attrname = obj.__name__
        modpath = sys.modules[obj.__module__].__file__
        calldefs = static_calldefs(modpath)
        ub.modpath_to_modname(modpath)
        calldef = calldefs[attrname]
        lineno = calldef.lineno
    return lineno

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接