Using the python inspect module, in a function, I would like to get the source code of the line that called that function.
So in the following situation:
def fct1():
# Retrieve the line that called me and extract 'a'
return an object containing name='a'
a = fct1()
I would like to retrieve the string "a = fct1()" in fct1
All I can do so far is to retrieve the code of the whole module with :
code = inspect.getsource(sys._getframe().f_back)
Please note that fct1() can be called many times in the main module.
Eventually, what I want is to retrieve the variable name "a" which is easy if I can get s = "a = fct1()" in fct1() :
a_name = s.split("=")[0].strip()
A really dumb solution would be to capture a stack trace and take the 2nd line:
import traceback
def fct1():
stack = traceback.extract_stack(limit=2)
print(traceback.format_list(stack)[0].split('\n')[1].strip()) # prints "a = fct1()"
return None
a = fct1()
@jtlz2 asked for it in a decorator
import traceback
def add_caller(func):
def wrapper(*args, **kwargs):
stack = traceback.extract_stack(limit=2)
func(*args, caller=traceback.format_list(stack)[0].split('\n')[1].strip(), **kwargs)
return wrapper
@add_caller
def fct1(caller):
print(caller)
fct1()
And it does work.
UPDATE Here's a functional version (which needed limit=3 for the caller of the caller):
import traceback
def source_line_of_caller():
"""Return the Python source code line that called your function."""
stack = traceback.extract_stack(limit=3)
return traceback.format_list(stack)[0].split('\n')[1].strip()
def _tester():
assert "_tester() # whoa, comments too" == source_line_of_caller()
_tester() # whoa, comments too