The Python Oracle

How to get the caller's method name in the called method?

--------------------------------------------------
Rise to the top 3% as a developer or hire one of them at Toptal: https://topt.al/25cXVn
--------------------------------------------------

Music by Eric Matyas
https://www.soundimage.org
Track title: Puzzle Game 2

--

Chapters
00:00 How To Get The Caller'S Method Name In The Called Method?
00:24 Accepted Answer Score 342
00:46 Answer 2 Score 130
00:58 Answer 3 Score 38
01:44 Answer 4 Score 90
01:50 Thank you

--

Full question
https://stackoverflow.com/questions/2654...

--

Content licensed under CC BY-SA
https://meta.stackexchange.com/help/lice...

--

Tags
#python #introspection

#avk47



ACCEPTED ANSWER

Score 342


inspect.getframeinfo and other related functions in inspect can help:

>>> import inspect
>>> def f1(): f2()
... 
>>> def f2():
...   curframe = inspect.currentframe()
...   calframe = inspect.getouterframes(curframe, 2)
...   print('caller name:', calframe[1][3])
... 
>>> f1()
caller name: f1

this introspection is intended to help debugging and development; it's not advisable to rely on it for production-functionality purposes.




ANSWER 2

Score 130


Shorter version:

import inspect

def f1(): f2()

def f2():
    print ('caller name:', inspect.stack()[1][3])

f1()

(with thanks to @Alex, and Stefaan Lippen)




ANSWER 3

Score 90


This seems to work just fine:

import sys
print sys._getframe().f_back.f_code.co_name



ANSWER 4

Score 38


I've come up with a slightly longer version that tries to build a full method name including module and class.

https://gist.github.com/2151727 (rev 9cccbf)

# Public Domain, i.e. feel free to copy/paste
# Considered a hack in Python 2

import inspect

def caller_name(skip=2):
    """Get a name of a caller in the format module.class.method

       `skip` specifies how many levels of stack to skip while getting caller
       name. skip=1 means "who calls me", skip=2 "who calls my caller" etc.

       An empty string is returned if skipped levels exceed stack height
    """
    stack = inspect.stack()
    start = 0 + skip
    if len(stack) < start + 1:
      return ''
    parentframe = stack[start][0]    

    name = []
    module = inspect.getmodule(parentframe)
    # `modname` can be None when frame is executed directly in console
    # TODO(techtonik): consider using __main__
    if module:
        name.append(module.__name__)
    # detect classname
    if 'self' in parentframe.f_locals:
        # I don't know any way to detect call from the object method
        # XXX: there seems to be no way to detect static method call - it will
        #      be just a function call
        name.append(parentframe.f_locals['self'].__class__.__name__)
    codename = parentframe.f_code.co_name
    if codename != '<module>':  # top level usually
        name.append( codename ) # function or a method

    ## Avoid circular refs and frame leaks
    #  https://docs.python.org/2.7/library/inspect.html#the-interpreter-stack
    del parentframe, stack

    return ".".join(name)