I tried this code-snippet inside a script named test.py
:
from inspect import *
def f1(p,r):
"""Return f1 score from p,r"""
return 2*p*r/(p+r)
print(getsourcelines(f1))
If I run this from terminal with python3 test.py
, it outputs the following :
(['def f1(p,r):\n', '\t"""Return f1 score from p,r"""\n', '\treturn 2*p*r/(p+r)\n'], 3)
But, if I run the same whole script line by line inside python shell, it throws a OSError
. This is what I tried in python shell along with the error :
>>> from inspect import *
>>>
>>> def f1(p,r):
... """Return f1 score from p,r"""
... return 2*p*r/(p+r)
...
>>> print(getsourcelines(f1))
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/usr/lib/python3.6/inspect.py", line 955, in getsourcelines
lines, lnum = findsource(object)
File "/usr/lib/python3.6/inspect.py", line 786, in findsource
raise OSError('could not get source code')
OSError: could not get source code
>>>
Why does inspect.getsourcelines(f1)
throws error inside python shell, but not when it is run form the file? Is there any other way to get the source lines of a function declared inside a python shell?
This is the expected behaviour. inspect
has only a limited support for builtin objects (not loaded from files).
It is explicit in other functions like getsourcefile
where the doc says:
This will fail with a TypeError if the object is a built-in module, class, or function.
Either if less explicit, the doc for getsourcelines
says (emphasize mine):
The source code is returned as a list of the lines corresponding to the object and the line number indicates where in the original source file the first line of code was found. An OSError is raised if the source code cannot be retrieved.
In the current versions, getsourcelines
try to locate the function in the current source file. As it cannot get the current source file for the functions declared outside of a file, it raises an exception.
The underlying cause, is that when python is started in interactive mode, the main module is a builtin module and has no __file__
attribute.