9

I want to get the line number of a python function in the source code. What i have in runtime is module, class, method objects

Had a look at inspect

inspect.getsourcelines(object)    

which also gives line number in result.

I see that for methods with decorators, line no. returned from above inspect function points to the actual decorator's source code rather than desired function's source code. So any way to workaround this? (i understand that interpreter does something like wrapping function inside decorator in runtime, but i might be wrong)

Hari
  • 384
  • 1
  • 6
  • 20

2 Answers2

6

There is no easy solution in the general case.

A decorator is a function that given a function returns a function, normally by "wrapping" it in a closure that performs the operation for which the decorator has been designed.

The file and line number information are not however in the function object itself and you cannot "fix" them by copying this information from the wrapped function to the wrapper. That data is instead contained in the code object of the function (available with .func_code), and it is shared among all closures you are going to create.

>>> def bar(x):
...     def foo():
...         return x
...     return foo
... 
>>> f1 = bar(1)
>>> f2 = bar(2)
>>> f1()
1
>>> f2()
2
>>> f1.func_code is f2.func_code
True
>>> 
6502
  • 112,025
  • 15
  • 165
  • 265
  • I see, thanks for the expln. Even with 'func_code' am getting the line no. of decorator source code. I will proceed with ignoring setting line no. for methods with any decorator. My question now is how to find that out a method has _any_ decorator or not (decorator name not known earlier) – Hari Dec 01 '11 at 12:12
  • @Hari: a decorator can return whatever it wants (even something that is not a closure or even just the same function that it got on input, possibly doing some other computation before returning it) so there is no 100% sure method to know if a function has been decorated or not given the function object. – 6502 Dec 02 '11 at 07:11
5

The wrapt module solves this problem by allowing you to write decorators which preserve the necessary metadata to find the source of a function as well as perform other introspection. It's like an improved functools.wraps.

Alex Hall
  • 34,833
  • 5
  • 57
  • 89