Reputation: 2075
I want to log all the names of functions where my code is going. It does not matter who is calling the function.
import inspect
def whoami():
return inspect.stack()[1][3]
def foo():
print(whoami())
Currently it prints foo
. I want it to print whoami
.
Upvotes: 40
Views: 50167
Reputation: 63282
This is probably the fastest implementation. It avoids the use of additional inspect
methods which can be slow or unnecessary.
Implementation:
from inspect import currentframe
def get_self_name() -> str:
return currentframe().f_code.co_name
def get_caller_name() -> str:
return currentframe().f_back.f_code.co_name
def get_parent_caller_name() -> str:
return currentframe().f_back.f_back.f_code.co_name
Usage:
def actual_function_1():
print('In actual_function_1:', get_self_name())
def actual_function_2():
print('In actual_function_2:', get_caller_name())
def actual_function_3() -> None:
print('In actual_function_3:', get_parent_caller_name())
actual_function_1()
actual_function_2()
actual_function_3()
Output:
In actual_function_1: get_self_name
In actual_function_2: actual_function_2
In actual_function_3: <module>
Upvotes: 1
Reputation: 624
This simple reusable method returns a name of the caller/parent function:
import inspect
def current_method_name():
# [0] is this method's frame, [1] is the parent's frame - which we want
return inspect.stack()[1].function
# Example:
def whoami():
print(current_method_name())
whoami()
-> output is whoami
Upvotes: 7
Reputation: 7134
Call sys._getframe()
to get a frame
class instance. The f_code.co_name
member holds the function name.
sys._getframe(0).f_code.co_name
Add a simple helper function func_name()
to wrap the call
import sys
def func_name():
return sys._getframe(1).f_code.co_name
def func1():
print(func_name())
func1() # prints 'func1'
Upvotes: 12
Reputation: 48038
Adding an answer here as it can be useful to include the class name as well as the function.
This checks for self
and cls
convention, to include the class name.
def name_of_caller(frame=1):
"""
Return "class.function_name" of the caller or just "function_name".
"""
frame = sys._getframe(frame)
fn_name = frame.f_code.co_name
var_names = frame.f_code.co_varnames
if var_names:
if var_names[0] == "self":
self_obj = frame.f_locals.get("self")
if self_obj is not None:
return type(self_obj).__name__ + "." + fn_name
if var_names[0] == "cls":
cls_obj = frame.f_locals.get("cls")
if cls_obj is not None:
return cls_obj.__name__ + "." + fn_name
return fn_name
Upvotes: 1
Reputation: 97571
For my logging purpose i want to log all the names of functions where my code is going
Have you considered decorators?
import functools
def logme(f):
@functools.wraps(f)
def wrapped(*args, **kwargs):
print(f.__name__)
return f(*args, **kwargs)
return wrapped
@logme
def myfunction():
print("Doing some stuff")
Upvotes: 19
Reputation:
Actually, Eric's answer points the way if this is about logging:
For my logging purpose i want to log all the names of functions where my code is going
You can adjust the formatter to log the function name:
import logging
def whoami():
logging.info("Now I'm there")
def foo():
logging.info("I'm here")
whoami()
logging.info("I'm back here again")
logging.basicConfig(
format="%(asctime)-15s [%(levelname)s] %(funcName)s: %(message)s",
level=logging.INFO)
foo()
prints
2015-10-16 16:29:34,227 [INFO] foo: I'm here
2015-10-16 16:29:34,227 [INFO] whoami: Now I'm there
2015-10-16 16:29:34,227 [INFO] foo: I'm back here again
Upvotes: 31
Reputation:
You probably want inspect.getframeinfo(frame).function
:
import inspect
def whoami():
frame = inspect.currentframe()
return inspect.getframeinfo(frame).function
def foo():
print(whoami())
foo()
prints
whoami
Upvotes: 57