python – Determine function name from within that function (without using traceback)

The Question :

530 people think this question is useful

In Python, without using the traceback module, is there a way to determine a function’s name from within that function?

Say I have a module foo with a function bar. When executing foo.bar(), is there a way for bar to know bar’s name? Or better yet, foo.bar‘s name?

#foo.py  
def bar():
    print "my name is", __myname__ # <== how do I calculate this at runtime?

The Question Comments :
  • I do not understand why the accepted answer is not that from Andreas Young (or any other that shows how to do it). Instead, the accepted answer is “you can’t do that”, which seems wrong; the only requirement by the OP was not using traceback. Not even the times of answers and comments seem to back it.

The Answer 1

223 people think this answer is useful

Python doesn’t have a feature to access the function or its name within the function itself. It has been proposed but rejected. If you don’t want to play with the stack yourself, you should either use "bar" or bar.__name__ depending on context.

The given rejection notice is:

This PEP is rejected. It is not clear how it should be implemented or what the precise semantics should be in edge cases, and there aren’t enough important use cases given. response has been lukewarm at best.

The Answer 2

442 people think this answer is useful
import inspect

def foo():
   print(inspect.stack()[0][3])
   print(inspect.stack()[1][3]) #will give the caller of foos name, if something called foo

The Answer 3

174 people think this answer is useful

There are a few ways to get the same result:

from __future__ import print_function
import sys
import inspect

def what_is_my_name():
    print(inspect.stack()[0][0].f_code.co_name)
    print(inspect.stack()[0][3])
    print(inspect.currentframe().f_code.co_name)
    print(sys._getframe().f_code.co_name)

Note that the inspect.stack calls are thousands of times slower than the alternatives:

$ python -m timeit -s 'import inspect, sys' 'inspect.stack()[0][0].f_code.co_name'
1000 loops, best of 3: 499 usec per loop
$ python -m timeit -s 'import inspect, sys' 'inspect.stack()[0][3]'
1000 loops, best of 3: 497 usec per loop
$ python -m timeit -s 'import inspect, sys' 'inspect.currentframe().f_code.co_name'
10000000 loops, best of 3: 0.1 usec per loop
$ python -m timeit -s 'import inspect, sys' 'sys._getframe().f_code.co_name'
10000000 loops, best of 3: 0.135 usec per loop

The Answer 4

49 people think this answer is useful

You can get the name that it was defined with using the approach that @Andreas Jung shows, but that may not be the name that the function was called with:

import inspect

def Foo():
   print inspect.stack()[0][3]

Foo2 = Foo

>>> Foo()
Foo

>>> Foo2()
Foo

Whether that distinction is important to you or not I can’t say.

The Answer 5

48 people think this answer is useful
functionNameAsString = sys._getframe().f_code.co_name

I wanted a very similar thing because I wanted to put the function name in a log string that went in a number of places in my code. Probably not the best way to do that, but here’s a way to get the name of the current function.

The Answer 6

26 people think this answer is useful

I keep this handy utility nearby:

import inspect
myself = lambda: inspect.stack()[1][3]

Usage:

myself()

The Answer 7

22 people think this answer is useful

I guess inspect is the best way to do this. For example:

import inspect
def bar():
    print("My name is", inspect.stack()[0][3])

The Answer 8

19 people think this answer is useful

I found a wrapper that will write the function name

from functools import wraps

def tmp_wrap(func):
    @wraps(func)
    def tmp(*args, **kwargs):
        print func.__name__
        return func(*args, **kwargs)
    return tmp

@tmp_wrap
def my_funky_name():
    print "STUB"

my_funky_name()

This will print

my_funky_name

STUB

The Answer 9

16 people think this answer is useful

This is actually derived from the other answers to the question.

Here’s my take:

import sys

# for current func name, specify 0 or no argument.
# for name of caller of current func, specify 1.
# for name of caller of caller of current func, specify 2. etc.
currentFuncName = lambda n=0: sys._getframe(n + 1).f_code.co_name


def testFunction():
    print "You are in function:", currentFuncName()
    print "This function's caller was:", currentFuncName(1)    


def invokeTest():
    testFunction()


invokeTest()

# end of file

The likely advantage of this version over using inspect.stack() is that it should be thousands of times faster [see Alex Melihoff’s post and timings regarding using sys._getframe() versus using inspect.stack() ].

The Answer 10

14 people think this answer is useful

print(inspect.stack()[0].function) seems to work too (Python 3.5).

The Answer 11

13 people think this answer is useful

Here’s a future-proof approach.

Combining @CamHart’s and @Yuval’s suggestions with @RoshOxymoron’s accepted answer has the benefit of avoiding:

  • _hidden and potentially deprecated methods
  • indexing into the stack (which could be reordered in future pythons)

So I think this plays nice with future python versions (tested on 2.7.3 and 3.3.2):

from __future__ import print_function
import inspect

def bar():
    print("my name is '{}'".format(inspect.currentframe().f_code.co_name))

The Answer 12

12 people think this answer is useful

I am not sure why people make it complicated:

import sys 
print("%s/%s" %(sys._getframe().f_code.co_filename, sys._getframe().f_code.co_name))

The Answer 13

11 people think this answer is useful
import inspect

def whoami():
    return inspect.stack()[1][3]

def whosdaddy():
    return inspect.stack()[2][3]

def foo():
    print "hello, I'm %s, daddy is %s" % (whoami(), whosdaddy())
    bar()

def bar():
    print "hello, I'm %s, daddy is %s" % (whoami(), whosdaddy())

foo()
bar()

In IDE the code outputs

hello, I’m foo, daddy is

hello, I’m bar, daddy is foo

hello, I’m bar, daddy is

The Answer 14

11 people think this answer is useful
import sys

def func_name():
    """
    :return: name of caller
    """
    return sys._getframe(1).f_code.co_name

class A(object):
    def __init__(self):
        pass
    def test_class_func_name(self):
        print(func_name())

def test_func_name():
    print(func_name())

Test:

a = A()
a.test_class_func_name()
test_func_name()

Output:

test_class_func_name
test_func_name

The Answer 15

8 people think this answer is useful

You can use a decorator:

def my_function(name=None):
    return name

def get_function_name(function):
    return function(name=function.__name__)

>>> get_function_name(my_function)
'my_function'

The Answer 16

3 people think this answer is useful

I do my own approach used for calling super with safety inside multiple inheritance scenario (I put all the code)

def safe_super(_class, _inst):
    """safe super call"""
    try:
        return getattr(super(_class, _inst), _inst.__fname__)
    except:
        return (lambda *x,**kx: None)


def with_name(function):
    def wrap(self, *args, **kwargs):
        self.__fname__ = function.__name__
        return function(self, *args, **kwargs)
return wrap

sample usage:

class A(object):

    def __init__():
        super(A, self).__init__()

    @with_name
    def test(self):
        print 'called from A\n'
        safe_super(A, self)()

class B(object):

    def __init__():
        super(B, self).__init__()

    @with_name
    def test(self):
        print 'called from B\n'
        safe_super(B, self)()

class C(A, B):

    def __init__():
        super(C, self).__init__()

    @with_name
    def test(self):
        print 'called from C\n'
        safe_super(C, self)()

testing it :

a = C()
a.test()

output:

called from C
called from A
called from B

Inside each @with_name decorated method you have access to self.__fname__ as the current function name.

The Answer 17

3 people think this answer is useful

I recently tried to use the above answers to access the docstring of a function from the context of that function but as the above questions were only returning the name string it did not work.

Fortunately I found a simple solution. If like me, you want to refer to the function rather than simply get the string representing the name you can apply eval() to the string of the function name.

import sys
def foo():
    """foo docstring"""
    print(eval(sys._getframe().f_code.co_name).__doc__)

The Answer 18

3 people think this answer is useful

I suggest not to rely on stack elements. If someone use your code within different contexts (python interpreter for instance) your stack will change and break your index ([0][3]).

I suggest you something like that:

class MyClass:

    def __init__(self):
        self.function_name = None

    def _Handler(self, **kwargs):
        print('Calling function {} with parameters {}'.format(self.function_name, kwargs))
        self.function_name = None

    def __getattr__(self, attr):
        self.function_name = attr
        return self._Handler


mc = MyClass()
mc.test(FirstParam='my', SecondParam='test')
mc.foobar(OtherParam='foobar')

The Answer 19

3 people think this answer is useful

This is pretty easy to accomplish with a decorator.

>>> from functools import wraps

>>> def named(func):
...     @wraps(func)
...     def _(*args, **kwargs):
...         return func(func.__name__, *args, **kwargs)
...     return _
... 

>>> @named
... def my_func(name, something_else):
...     return name, something_else
... 

>>> my_func('hello, world')
('my_func', 'hello, world')

The Answer 20

0 people think this answer is useful

Use __name__ attribute:

# foo.py
def bar():
    print(f"my name is {bar.__name__}")

You can easily access function’s name from within the function using __name__ attribute.

>>> def bar():
...     print(f"my name is {bar.__name__}")
...
>>> bar()
my name is bar

I’ve come across this question myself several times, looking for the ways to do it. Correct answer is contained in the Python’s documentation (see Callable types section).

Every function has a __name__ parameter that returns its name and even __qualname__ parameter that returns its full name, including which class it belongs to (see Qualified name).

Add a Comment