Johannes C.
Johannes C.

Reputation: 93

Can I know from where a function has been invoked/called?

I'm starting to program in Python 3. And I was wondering if there is any function or method that allows me to know from which place (perhaps, from which line) the function was invoked.

For example, if I have the following code...

1  def foo():
2      print("Hi!")
3
4  def suma(a, b):
5      return a+b
6
7
8  def main():
9      foo()
10     suma(3,6)
11
12 
13 if __name__ == "__main__":
14     main()
15 else:
16     print("Function main() not exist")
17

Somehow know that the function:

foo: It is defined in line 1. It has been called from main on line 9

suma: It is defined in line 4. It has been called from main on line 10.

Is there some function that does this or maybe something similar?

Maybe something like:

foo.__ code __. co_nlocals
suma.__ code __. co_nlocals

But with the aforementioned.

Upvotes: 2

Views: 2308

Answers (2)

Federica F.
Federica F.

Reputation: 235

  • Line number in which the function is defined.

    Use: inspect.getsourcelines(THE_NAME_OF_YOUR_FUNCTION)[1]

  • Line from which the function has been.

    Use: called.inspect.stack()[1][2]

  • Invoking/calling function.

    Use: inspect.stack()[1][3]

  • (optional) Module in which it is contained.

    Use: THE_NAME_OF_YOUR_FUNCTION.__module__

As an example ... (I have added an additional function X)

import inspect

def foo(msg):
    print(msg)
    ###▼ YOUR INSPECTION CODE ▼###
    print("\t«{}»\tLine number in which the function is defined.".
           format(inspect.getsourcelines(foo)[1]))
    print("\t«{}»\tLine from which the function has been called.".
           format(inspect.stack()[1][2]))
    print("\t«{}»\tInvoking/calling function.".format(inspect.stack()[1][3]))
    print("\t«{}»\tModule in which it is contained.\n".format(foo.__module__))

def suma(a, b):
    foo("Call from [suma()], on the line [14]")
    return a+b

def difference(a, b):
    foo("Call from [difference()], on the line [18]")
    return a-b

def main():
    foo("Call from [main()], on the line [22]")
    suma(3,6)
    foo("Call from [main()], on the line [24]")
    difference(5,2)

if __name__ == "__main__":
    main()

If we list the previous lines, the code would be as follows:

01    import inspect
02    
03    def foo(msg):
04        print(msg)
05        ###▼ YOUR INSPECTION CODE ▼###
06        print("\t«{}»\tLine number in which the function is defined.".
07               format(inspect.getsourcelines(foo)[1]))
08        print("\t«{}»\tLine from which the function has been called.".
09               format(inspect.stack()[1][2]))
10        print("\t«{}»\tInvoking/calling function.".format(inspect.stack()[1][3]))
11        print("\t«{}»\tModule in which it is contained.\n".format(foo.__module__))
12    
13    def suma(a, b):
14        foo("Call from [suma()], on the line [14]")
15        return a+b
16    
17    def difference(a, b):
18        foo("Call from [difference()], on the line [18]")
19        return a-b
20    
21    def main():
22        foo("Call from [main()], on the line [22]")
23        suma(3,6)
24        foo("Call from [main()], on the line [24]")
25        difference(5,2)
26    
27    if __name__ == "__main__":
28        main()

You will get as a result:

Call from [main()], on the line [22]
    «3»     Line number in which the function is defined.
    «22»    Line from which the function has been called.
    «main»  Invoking/calling function.
    «__main__»  Module in which it is contained.

Call from [suma()], on the line [14]
    «3»     Line number in which the function is defined.
    «14»    Line from which the function has been called.
    «suma»  Invoking/calling function.
    «__main__»  Module in which it is contained.

Call from [main()], on the line [24]
    «3»     Line number in which the function is defined.
    «24»    Line from which the function has been called.
    «main»  Invoking/calling function.
    «__main__»  Module in which it is contained.

Call from [difference()], on the line [18]
    «3»     Line number in which the function is defined.
    «18»    Line from which the function has been called.
    «difference»    Invoking/calling function.
    «__main__»  Module in which it is contained.

Upvotes: 3

Tyler Rosacker
Tyler Rosacker

Reputation: 102

the inspect module is how you'd want to go about this (and specifically the .getsourcelines() method).

def foo():
    print("Hi!")
    
def suma(a, b):
    return a+b

import inspect
print(inspect.getsourcelines(foo))
print(inspect.getsourcelines(suma))

(['def foo():\n', ' print("Hi!")\n'], 1)
(['def suma(a, b):\n', ' return a+b\n'], 4)

You'll see that the result is a tupple where the first element is the source of the function, and the second element is the line where the function was defined.

There is an equivalent getsourcefile method to get the file if you need that as well.

Upvotes: -1

Related Questions