1047

How do I get a function's name as a string?

def foo():
    pass

>>> name_of(foo)
"foo"
Mateen Ulhaq
  • 24,552
  • 19
  • 101
  • 135
X10
  • 17,155
  • 7
  • 30
  • 28

14 Answers14

1350
my_function.__name__

Using __name__ is the preferred method as it applies uniformly. Unlike func_name, it works on built-in functions as well:

>>> import time
>>> time.time.func_name
Traceback (most recent call last):
  File "<stdin>", line 1, in ?
AttributeError: 'builtin_function_or_method' object has no attribute 'func_name'
>>> time.time.__name__ 
'time'

Also the double underscores indicate to the reader this is a special attribute. As a bonus, classes and modules have a __name__ attribute too, so you only have remember one special name.

user28409
  • 38,712
  • 2
  • 17
  • 5
  • 446
    Because in some cases, you get some function object as an argument to your function, and you need to display/store/manipulate that function's name. Perhaps you're generating documentation, help text, a history of actions, etc. So no, you're not always hardcoding the function name. – mbargiel Jul 26 '13 at 14:17
  • 2
    @mgargiel: What I meant to say is: supposing you have a class which defines 100 methods, where all methods are only wrappers, which call a private method, passing the name of the wrapper itself. Something like this: ``def wrapper(kwargs): super(ExtendedClass,self).call('wrapper', kwargs)``. You have another choice, which is: ``def wrapper(kwargs): super(ExtendedClass,self).call(sys._getframe().f_code.co_name, kwargs)``. So, the answer from Albert Vonpupp looks better to me. – Richard Gomes Aug 30 '13 at 19:20
  • 19
    @RichardGomes One answer is appropriate for getting the name within the function itself, the other is appropriate for getting it from a function reference. The OP's question as written indicates the latter. – Russell Borogove Aug 31 '13 at 00:44
  • 27
    @RichardGomes Actually I came to this question looking for a solution to this problem. The problem I'm trying to address is create a decorator that can be used to log all my calls. – ali-hussain Sep 18 '13 at 19:36
  • 24
    @RichardGomes functions are first-class objects, there can be more than name bound to them. It is not necessarily the case that `f.__name__ == 'f'`. – wim Mar 13 '14 at 20:13
  • 1
    I don't see this solution being of any help since most people would only use this if they want something generic that you can call as a method many times. Such a method would be good if you want to track the order of running functions. The solution above is saying my function is foo and calling foo._name__ and then setting it to a variable name. You might as well just set a string with the value foo. The _getframe() call described below as another solution works inside multiple functions inside one class! exactly what I needed. – Eamonn Kenny Dec 04 '17 at 11:40
  • @EamonnKenny I've written a decorator that takes a generic function as input. Under certain cases, it raises an error if the method cannot be supported. My exception reports back the unsupported method name in the exception message. `__name__` solves this. – jonathan Apr 20 '18 at 17:49
  • 2
    @RichardGomes my use case is for debugging a functional programming function. I have a function that accepts a function as an argument and I want to log the name of the function that was passed – DVL Aug 23 '19 at 19:52
408

To get the current function's or method's name from inside it, consider:

import inspect

this_function_name = inspect.currentframe().f_code.co_name

sys._getframe also works instead of inspect.currentframe although the latter avoids accessing a private function.

To get the calling function's name instead, consider f_back as in inspect.currentframe().f_back.f_code.co_name.


If also using mypy, it can complain that:

error: Item "None" of "Optional[FrameType]" has no attribute "f_code"

To suppress the above error, consider:

import inspect
import types
from typing import cast

this_function_name = cast(types.FrameType, inspect.currentframe()).f_code.co_name
Asclepius
  • 57,944
  • 17
  • 167
  • 143
Albert Vonpupp
  • 4,557
  • 1
  • 17
  • 20
  • 63
    +1: This is the answer I'd like to see. Other answers assume that the caller already knows the function name, which is nonsense in the context of this question. – Richard Gomes Jul 11 '13 at 16:43
  • 126
    Richard: no it doesn't. YOU are assuming that you're calling __name__ or func_name on your function directly in the same scope it was defined, which very often isn't the case. Keep in mind that functions are objects - they can be passed around as arguments to other functions, stored in lists/dicts for later lookups or execution, etc. – mbargiel Jul 26 '13 at 14:24
  • 13
    @paulus_almighty, digging into stack frames doesn't strike me as abstract! In fact, it's kind of the opposite of abstract. See the [implementation detail](https://docs.python.org/2/library/sys.html#sys._getframe) note in the docs. Not all implementations of Python will include `sys._getframe` -- it's directly connected to the internals of CPython. – senderle Jan 31 '16 at 14:42
  • 7
    This only works inside the function, but the question specifies that the function shouldn't be called. – user2357112 Mar 29 '16 at 00:02
  • 6
    Case you wanna wrap your function to something more usable and easy to remember u have to retrieve frame 1 like `sys._getframe(1).f_code.co_name`, so you can define a function like `get_func_name()` and expect to get the desired name of the function who invoked. – m3nda Jan 04 '17 at 10:39
  • 1
    @Igor, `sys._getframe()`, gets a n frame, case of `sys._getframe(1)` will take a "one deep level" frame from the list/stack. So, if you wrap the call between a class->function->function, you'll need to pass the number of functions/classes that has called it. It's a bit weird, but simple. In a single and direct call, doing `sys._getframe()` means `sys._getframe(0)`, and cuz it was not explictly told u can't guess magically that you can pass numbers. You're welcome. – m3nda Feb 16 '17 at 03:30
  • piggybacking on this answer: the raiseValueError line is a universal docstring caller! You do not need to type the function name!: line 1: `if not some_input:` line 2 `....raise ValueError(f'No input received. \n\t{eval(inspect.currentframe().f_code.co_name).__doc__}')` – spioter Apr 15 '21 at 17:16
50

If you're interested in class methods too, Python 3.3+ has __qualname__ in addition to __name__.

def my_function():
    pass

class MyClass(object):
    def method(self):
        pass

print(my_function.__name__)         # gives "my_function"
print(MyClass.method.__name__)      # gives "method"

print(my_function.__qualname__)     # gives "my_function"
print(MyClass.method.__qualname__)  # gives "MyClass.method"
lapis
  • 6,872
  • 4
  • 35
  • 40
  • If method has the @property decorator, this does not work, any way to access the name in this instance? – dusio Nov 28 '20 at 18:13
  • 3
    @dusiod, looks like you can get the name/qualname from the property's getter (which you create using the @property decorator): `MyClass.prop.fget.__qualname__` gives `MyClass.prop`. – lapis Nov 30 '20 at 13:59
47
my_function.func_name

There are also other fun properties of functions. Type dir(func_name) to list them. func_name.func_code.co_code is the compiled function, stored as a string.

import dis
dis.dis(my_function)

will display the code in almost human readable format. :)

Markus Jarderot
  • 86,735
  • 21
  • 136
  • 138
  • 5
    What is the difference between f.__name__ and f.func_name? – Federico A. Ramponi Oct 30 '08 at 19:43
  • double underscore names are traditionally regarded as private though never enforced. So it is better to use func_name even though they may be the same. – Sam Corder Oct 30 '08 at 20:11
  • 16
    Sam: __names are private, __names__ are special, there's a conceptual difference. – Matthew Trevor Oct 31 '08 at 03:15
  • 14
    In case someone is puzzled by the preceding answer by Matthew, the comment system has interpreted some double-underscores as code for bold. Escaped with backtick, the message should read: `__names__` are private, `__names` are special. – gwideman Feb 20 '14 at 21:34
  • @MatthewTrevor, do you have a reference for more information/specifics? – rivy Mar 12 '14 at 12:51
  • 17
    Actually, I think the correct is `_names` are private (single underscore before, just a convention), `__names__` are special (double underscores before and after). Not sure if double underscore before has any meaning, formally or as a convention. – MestreLion Aug 23 '14 at 08:48
  • 3
    @MestreLion It's called [name mangling](https://docs.python.org/2/tutorial/classes.html#private-variables-and-class-local-references). – alexia Apr 07 '15 at 11:59
  • @nyuszika7h: true, I forgot about name mangling. So I guess the best advise is: use the *convention* `_name` for "ordinary" private members, as `__name` is subject to name mangling and `__name__` may be "special" depending on `name`, unless either are what you want and you know what you're doing. – MestreLion Apr 09 '15 at 03:47
  • 20
    `func_name` doesn't exist any more in python3 so you need to use `func.__name__` if you want compatibility – Daenyth Apr 07 '17 at 15:50
39

This function will return the caller's function name.

def func_name():
    import traceback
    return traceback.extract_stack(None, 2)[0][2]

It is like Albert Vonpupp's answer with a friendly wrapper.

Demyn
  • 1,210
  • 1
  • 14
  • 14
38
import inspect

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

where

  • stack()[0] is the caller

  • stack()[3] is the string name of the method

lfurini
  • 3,729
  • 4
  • 30
  • 48
Ma Guowei
  • 651
  • 6
  • 5
  • 2
    Plain and simple. `stack()[0]` will always be the caller, `[3]` the string name of the method. – kontur Oct 28 '19 at 13:04
29

I like using a function decorator. I added a class, which also times the function time. Assume gLog is a standard python logger:

class EnterExitLog():
    def __init__(self, funcName):
        self.funcName = funcName

    def __enter__(self):
        gLog.debug('Started: %s' % self.funcName)
        self.init_time = datetime.datetime.now()
        return self

    def __exit__(self, type, value, tb):
        gLog.debug('Finished: %s in: %s seconds' % (self.funcName, datetime.datetime.now() - self.init_time))

def func_timer_decorator(func):
    def func_wrapper(*args, **kwargs):
        with EnterExitLog(func.__name__):
            return func(*args, **kwargs)

    return func_wrapper

so now all you have to do with your function is decorate it and voila

@func_timer_decorator
def my_func():
radato
  • 840
  • 9
  • 27
22

You just want to get the name of the function here is a simple code for that. let say you have these functions defined

def function1():
    print "function1"

def function2():
    print "function2"

def function3():
    print "function3"
print function1.__name__

the output will be function1

Now let say you have these functions in a list

a = [function1 , function2 , funciton3]

to get the name of the functions

for i in a:
    print i.__name__

the output will be

function1
function2
function3

Mohsin Ashraf
  • 972
  • 12
  • 18
21

As an extension of @Demyn's answer, I created some utility functions which print the current function's name and current function's arguments:

import inspect
import logging
import traceback

def get_function_name():
    return traceback.extract_stack(None, 2)[0][2]

def get_function_parameters_and_values():
    frame = inspect.currentframe().f_back
    args, _, _, values = inspect.getargvalues(frame)
    return ([(i, values[i]) for i in args])

def my_func(a, b, c=None):
    logging.info('Running ' + get_function_name() + '(' + str(get_function_parameters_and_values()) +')')
    pass

logger = logging.getLogger()
handler = logging.StreamHandler()
formatter = logging.Formatter(
    '%(asctime)s [%(levelname)s] -> %(message)s')
handler.setFormatter(formatter)
logger.addHandler(handler)
logger.setLevel(logging.INFO)

my_func(1, 3) # 2016-03-25 17:16:06,927 [INFO] -> Running my_func([('a', 1), ('b', 3), ('c', None)])
Community
  • 1
  • 1
Jim G.
  • 15,141
  • 22
  • 103
  • 166
18

sys._getframe() is not guaranteed to be available in all implementations of Python (see ref) ,you can use the traceback module to do the same thing, eg.

import traceback
def who_am_i():
   stack = traceback.extract_stack()
   filename, codeline, funcName, text = stack[-2]

   return funcName

A call to stack[-1] will return the current process details.

nucsit026
  • 652
  • 7
  • 16
sandyc
  • 199
  • 1
  • 3
  • Sorry, if `sys._getframe()` is undefined, then `traceback.extract_stack` is also inoperable. The latter provides a rough superset of the functionality of the former; you cannot expect to see one without the other. And in fact, in IronPython 2.7 `extract_stack()` always returns `[]`. -1 – SingleNegationElimination Aug 31 '13 at 01:06
16

I've seen a few answers that utilized decorators, though I felt a few were a bit verbose. Here's something I use for logging function names as well as their respective input and output values. I've adapted it here to just print the info rather than creating a log file and adapted it to apply to the OP specific example.

def debug(func=None):
    def wrapper(*args, **kwargs):
        try:
            function_name = func.__func__.__qualname__
        except:
            function_name = func.__qualname__
        return func(*args, **kwargs, function_name=function_name)
    return wrapper

@debug
def my_function(**kwargs):
    print(kwargs)

my_function()

Output:

{'function_name': 'my_function'}
NL23codes
  • 1,181
  • 1
  • 14
  • 31
  • 2
    What I like about this as opposed to all the others, is that by just adding the `debug` function once you can add the functionality by simply adding the decorator to whatever function you need or want to print the function name. It's seems to be the easiest and the most adaptable. – spareTimeCoder Apr 14 '20 at 19:32
  • 1
    Why is the try/except needed? When is `__qualname__` available directly and when it is not? – Geraldo B. Landre Sep 24 '21 at 16:11
10
import inspect

def my_first_function():
    func_name = inspect.stack()[0][3]
    print(func_name)  # my_first_function

or:

import sys

def my_second_function():
    func_name = sys._getframe().f_code.co_name
    print(func_name)  # my_second_function
Szczerski
  • 839
  • 11
  • 11
10

You can get a function's name as a string by using the special __name__ variable.

def my_function():
    pass

print(my_function.__name__) # prints "my_function"
Gustin
  • 181
  • 2
  • 5
  • This is new right? When did it come to be? – Beefy_Swain Jun 17 '23 at 21:44
  • 1
    @Beefy_Swain the `__name__` special variable has been a part of the language since at least Python 2.0 (released in 2000) and likely dates as far back as the late 90s. – Gustin Aug 02 '23 at 05:18
5

Try

import sys
fn_name = sys._getframe().f_code.co_name

further reference https://www.oreilly.com/library/view/python-cookbook/0596001673/ch14s08.html

Ahmed Shehab
  • 1,657
  • 15
  • 24