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

输出:

喷火 < module_caller_of_foo >

其他回答

Python没有在函数本身中访问函数或其名称的特性。它已经被提出,但被否决了。如果你不想自己玩堆栈,你应该使用“bar”或bar。__name__取决于上下文。

给定的拒绝通知为:

此PEP被拒绝。它不清楚应该如何实现,也不清楚在边缘情况下应该有什么精确的语义,而且没有给出足够重要的用例。人们的反应充其量也只是不温不火。

这是一个经得起考验的方法。

将@CamHart和@Yuval的建议与@RoshOxymoron接受的答案结合起来,可以避免:

_hidden和潜在弃用的方法 在堆栈中建立索引(可以在未来的python中重新排序)

所以我认为这对未来的python版本(在2.7.3和3.3.2测试)很有帮助:

from __future__ import print_function
import inspect

def bar():
    print("my name is '{}'".format(inspect.currentframe().f_code.co_name))

更新:在3.7.10,3.8.10和3.9.5测试

.f_back.f_code Sincesys._getframe()。Co_name在python 3.9中根本不起作用,下面可以从现在开始使用:

from inspect import currentframe


def testNameFunction() -> str:
    return currentframe().f_back.f_code.co_name


print(f'function name is {testNameFunction()}(...)')

结果:

function name is testNameFunction(...)

我最近尝试使用上面的答案从该函数的上下文中访问函数的文档字符串,但由于上面的问题只返回名称字符串,因此不起作用。

幸运的是,我找到了一个简单的解决办法。如果像我一样,想要引用函数,而不是简单地获取表示名称的字符串,那么可以对函数名称的字符串应用eval()。

import sys
def foo():
    """foo docstring"""
    print(eval(sys._getframe().f_code.co_name).__doc__)

我不知道为什么人们会把它弄得这么复杂:

import sys 
print("%s/%s" %(sys._getframe().f_code.co_filename, sys._getframe().f_code.co_name))