Reputation: 177
suppose I have a module named test.py. In this file, I know a class named dummy. How to get the line number of class dummy definition after I import it?
Is there an API can do such thing?
if dummy is a function, then dummy.__code__.co_firstlineno
will return the line no. But if dummy is a class, it doesn't have__code__
attribute
I wanna know is there a way which can return the line no without parsing the file.
Upvotes: 12
Views: 4394
Reputation: 25039
Starting from python 3.13, You can use type.__firstlineno__
attribute.
The line number of the first line of the class definition, including decorators. Setting the
__module__
attribute removes the__firstlineno__
item from the type’s dictionary.Added in version 3.13.
from test import dummy
print(dummy.__firstlineno__)
Upvotes: 1
Reputation: 5548
inspect.findsource(test.dummy)[1]
provides the line number via regex search in the source file (rather slow).
If you define the class, line numbers could be exposed like this:
class MyClass:
def test_01(self):
assert 1
_classline_ = inspect.currentframe().f_code.co_firstlineno
_thisline_ = inspect.currentframe().f_lineno
Update 2020 / Python 3.9+ : inspect.findsource
now uses (slow) ast
instead of regex. (bpo-35113 / commit 696136b9)
Upvotes: 7
Reputation: 5248
This requires static analysis code I wrote for the xdoctest
module. I'm not sure it solves 100% of the cases, but I think it is more robust than a regex search.
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
Upvotes: 1
Reputation: 583
Look at the Retrieving source code section of inspect
. Try getsourcefile()
and getsourcelines()
.
Upvotes: 3