ChatGPT解决这个技术问题 Extra ChatGPT

How to get a function name as a string?

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

def foo():
    pass

>>> name_of(foo)
"foo"

u
user28409
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.


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.
@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.
@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.
@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.
@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'.
A
Asclepius

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

+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: 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.
@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 note in the docs. Not all implementations of Python will include sys._getframe -- it's directly connected to the internals of CPython.
This only works inside the function, but the question specifies that the function shouldn't be called.
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.
M
Markus Jarderot
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. :)


What is the difference between f.__name__ and f.func_name?
Sam: names are private, __names are special, there's a conceptual difference.
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.
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.
func_name doesn't exist any more in python3 so you need to use func.__name__ if you want compatibility
l
lapis

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"

If method has the @property decorator, this does not work, any way to access the name in this instance?
@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.
D
Demyn

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.


I had "" at index [2], but the following worked: traceback.extract_stack(None, 2)[0][-1]
for me this doesn't work, but this does: traceback.extract_stack()[-1][2]
This works if change the first index to 1, you folks should learn to debug before commenting... traceback.extract_stack(None, 2)[1][2]
l
lfurini
import inspect

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

where

stack()[0] is the caller

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


Plain and simple. stack()[0] will always be the caller, [3] the string name of the method.
r
radato

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():

M
Mohsin Ashraf

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


C
Community

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)])

n
nucsit026

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.


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
N
NL23codes

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'}

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.
Why is the try/except needed? When is __qualname__ available directly and when it is not?
S
Szczerski
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

A
Ahmed Shehab

Try

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

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


G
Gustin

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"