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?
Answers:
Thank you for visiting the Q&A section on Magenaut. Please note that all the answers may not help you solve the issue immediately. So please treat them as advisements. If you found the post helpful (or not), leave a comment & I’ll get back to you as soon as possible.
Method 1
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 foo()
output:
foo <module_caller_of_foo>
Method 2
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.
Method 3
There are few ways to get the same result:
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
Update 08/2021 (original post was written for Python2.7)
Python 3.9.1 (default, Dec 11 2020, 14:32:07) [GCC 7.3.0] :: Anaconda, Inc. on linux python -m timeit -s 'import inspect, sys' 'inspect.stack()[0][0].f_code.co_name' 500 loops, best of 5: 390 usec per loop python -m timeit -s 'import inspect, sys' 'inspect.stack()[0][3]' 500 loops, best of 5: 398 usec per loop python -m timeit -s 'import inspect, sys' 'inspect.currentframe().f_code.co_name' 2000000 loops, best of 5: 176 nsec per loop python -m timeit -s 'import inspect, sys' 'sys._getframe().f_code.co_name' 5000000 loops, best of 5: 62.8 nsec per loop
Method 4
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.
Method 5
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.
Method 6
I keep this handy utility nearby:
import inspect myself = lambda: inspect.stack()[1][3]
Usage:
myself()
Method 7
I guess inspect is the best way to do this. For example:
import inspect
def bar():
print("My name is", inspect.stack()[0][3])
Method 8
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
Method 9
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() ].
Method 10
print(inspect.stack()[0].function) seems to work too (Python 3.5).
Method 11
Here’s a future-proof approach.
Combining @CamHart’s and @Yuval’s suggestions with @RoshOxymoron’s accepted answer has the benefit of avoiding:
_hiddenand 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))
Update: tested on 3.7.10, 3.8.10, and 3.9.5
Method 12
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))
Method 13
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
Method 14
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
Method 15
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'
Method 16
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).
Method 17
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')
Method 18
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')
Method 19
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 An'
safe_super(A, self)()
class B(object):
def __init__():
super(B, self).__init__()
@with_name
def test(self):
print 'called from Bn'
safe_super(B, self)()
class C(A, B):
def __init__():
super(C, self).__init__()
@with_name
def test(self):
print 'called from Cn'
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.
Method 20
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__)
Method 21
Sincesys._getframe().f_back.f_code.co_name does not work at all in python 3.9, following could be used from now:
from inspect import currentframe
def testNameFunction() -> str:
return currentframe().f_back.f_code.co_name
print(f'function name is {testNameFunction()}(...)')
Result:
function name is testNameFunction(...)
Method 22
I like the idea of using a decorator but I’d prefer to avoid touching the function arguments. Hence, I’m providing yet another alternative:
import functools
def withname(f):
@functools.wraps(f)
def wrapper(*args, **kwargs):
global __name
__saved_name = globals().get("__name")
__name = f.__name__
ret = f(*args, **kwargs)
__name = __saved_name
return ret
return wrapper
@withname
def f():
print(f"in f: __name=={__name}")
g()
print(f"back in f: __name=={__name}")
@withname
def g():
print(f"in g: __name=={__name}")
We need to save and restore __name when calling the function as consequence of it being a global variable. Calling f() above produces:
in f: __name==f in g: __name==g back in f: __name==f
Unfortunately, there is no alternative to the global variable if we don’t change the function arguments. Referencing a variable, that is not created in the context of the function, will generate code that would look for a global variable:
>>> def f(): print(__function__)
>>> from dis import dis
>>> dis(f)
1 0 LOAD_GLOBAL 0 (print)
2 LOAD_GLOBAL 1 (__function__)
4 CALL_FUNCTION 1
6 POP_TOP
8 LOAD_CONST 0 (None)
10 RETURN_VALUE
Method 23
str(str(inspect.currentframe())).split(' ')[-1][:-1]
Method 24
import inspect
def method_name():
return inspect.stack()[1][3]
def method_name_caller():
return inspect.stack()[2][3]
def asdf():
print(method_name_caller())
print(method_name())
def asdf2():
print(method_name_caller())
print(method_name())
asdf()
Method 25
@jeff-laughlin’s answer is beautiful. I have modified it slightly to achieve what I think is the intent: to trace out the execution of functions, and also to capture the list of arguments as well as the keyword arguments. Thank you @jeff-laughlin!
from functools import wraps
import time
def named(func):
@wraps(func)
def _(*args, **kwargs):
print(f"From wrapper function: Executing function named: {func.__name__}, with arguments: {args}, and keyword arguments: {kwargs}.")
print(f"From wrapper function: {func}")
start_time = time.time()
return_value = func(*args, **kwargs)
end_time = time.time()
elapsed_time = end_time - start_time
print(f"From wrapper function: Execution of {func.__name__} took {elapsed_time} seconds.")
return return_value
return _
@named
def thanks(message, concepts, username='@jeff-laughlin'):
print(f"From inner function: {message} {username} for teaching me about the {concepts} concepts of closures and decorators!")
thanks('Thank you', 'two', username='@jeff-laughlin')
print('-'*80)
thanks('Thank you', 'two', username='stackoverflow')
print(thanks)
From wrapper function: Executing function named: thanks, with arguments: (‘Thank you’, ‘two’), and keyword arguments: {‘username’: ‘@jeff-laughlin’}.
From wrapper function: <function thanks at 0x7f13e6ceaa60>
From inner function: Thank you @jeff-laughlin for teaching me about the two concepts of closures and decorators!
From wrapper function: Execution of thanks took 2.193450927734375e-05 seconds.
——————————————————————————–
From wrapper function: Executing function named: thanks, with arguments: (‘Thank you’, ‘two’), and keyword arguments: {‘username’: ‘stackoverflow’}.
From wrapper function: <function thanks at 0x7f13e6ceaa60>
From inner function: Thank you stackoverflow for teaching me about the two concepts of closures and decorators!
From wrapper function: Execution of thanks took 7.152557373046875e-06 seconds.
<function thanks at 0x7f13e6ceaca0>
What is most surprising to me is that there is a way to intercept functions at runtime, inspect them, and take some actions based on this. The other surprising thing is the memory address of the inner function was the same both times. Does anyone know why this is? I have a ways to go before I can understand this decorator/closure magic.
All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0