在Python中,如果不使用traceback模块,是否有一种方法可以从函数内部确定函数的名称?
假设我有一个模块foo和一个功能栏。当执行foo.bar()时,是否有一种方法让bar知道bar的名字?或者更好的是,foo。酒吧的名字吗?
#foo.py
def bar():
print "my name is", __myname__ # <== how do I calculate this at runtime?
在Python中,如果不使用traceback模块,是否有一种方法可以从函数内部确定函数的名称?
假设我有一个模块foo和一个功能栏。当执行foo.bar()时,是否有一种方法让bar知道bar的名字?或者更好的是,foo。酒吧的名字吗?
#foo.py
def bar():
print "my name is", __myname__ # <== how do I calculate this at runtime?
当前回答
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())
测试:
a = A()
a.test_class_func_name()
test_func_name()
输出:
test_class_func_name
test_func_name
其他回答
实现您自己的装饰器
# mydecorators.py
def resolve_function(func):
#in case annotated func is an staticmethod
if isinstance(func,staticmethod):
return func.__func__
return func
def print_my_name(func):
def function_caller(*args,**kwargs):
_func = resolve_function(func)
print("my name is: %s" %_func.__name__)
return _func(*args,**kwargs)
return function_caller
然后使用它
# foo.py
from mydecorators import *
@print_my_name
def bar():
#do something else
#in terminal: my name is: bar
我找到了一个包装器,它将写入函数名
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()
这将打印
my_funky_name 存根
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())
测试:
a = A()
a.test_class_func_name()
test_func_name()
输出:
test_class_func_name
test_func_name
我把这个实用工具放在附近:
import inspect
myself = lambda: inspect.stack()[1][3]
用法:
myself()
从上面所有使用inspect库的答案来看,所有的都是这样写的:
import inspect
inspect.stack()[0][3]
但是,由于inspect.stack()的返回,[0]是一个NamedTuple,其形式为:
FrameInfo(frame=<frame at 0x103578810, file '<stdin>', line 1, code <module>>, filename='<stdin>', lineno=1, function='<module>', code_context=None, index=None)
可以简单地通过名称调用,即inspect.stack()[0].function
这里可以看到一个小的虚拟例子:
def test_train_UGRIZY_noZ(self, architecture, dataset, hyperrun, wloss):
log.warning(f"{inspect.stack()[0].function} -- Not Implemented Yet")
pass
当运行时打印:
WARNING - test_train_UGRIZY_noZ -- Not Implemented Yet