如何在被调用的方法中获得调用者的方法名?

假设我有两个方法:

def method1(self):
    ...
    a = A.method2()

def method2(self):
    ...

如果我不想为method1做任何改变,如何获得调用者的名字(在这个例子中,名字是method1)在method2?


当前回答

您可以使用装饰器,而不必使用stacktrace

如果您想在类中修饰一个方法

import functools

# outside ur class
def printOuterFunctionName(func):
@functools.wraps(func)
def wrapper(self):
    print(f'Function Name is: {func.__name__}')
    func(self)    
return wrapper 

class A:
  @printOuterFunctionName
  def foo():
    pass

你可以删除functools, self,如果它是过程性的

其他回答

代码:

#!/usr/bin/env python
import inspect

called=lambda: inspect.stack()[1][3]

def caller1():
    print "inside: ",called()

def caller2():
    print "inside: ",called()
    
if __name__=='__main__':
    caller1()
    caller2()

输出:

shahid@shahid-VirtualBox:~/Documents$ python test_func.py 
inside:  caller1
inside:  caller2
shahid@shahid-VirtualBox:~/Documents$

较短的版本:

import inspect

def f1(): f2()

def f2():
    print 'caller name:', inspect.stack()[1][3]

f1()

(感谢@Alex和Stefaan Lippen)

嘿,伙计,我曾经为我的应用程序做了3个没有插件的方法,也许这可以帮助你,它对我有用,所以可能对你也有用。

def method_1(a=""):
    if a == "method_2":
        print("method_2")

    if a == "method_3":
        print("method_3")


def method_2():
    method_1("method_2")


def method_3():
    method_1("method_3")


method_2()

我将使用inspect.currentframe().f_back.f_code.co_name。它的用法在之前的回答中没有涉及,主要有三种类型:

一些先前的答案使用inspect。堆栈,但它是众所周知的太慢。 一些先前的回答使用sys。_getframe是一个内部私有函数,因为它有前导下划线,所以不鼓励使用它。 一个先前的答案使用inspect.getouterframes(inspect.currentframe(), 2)[1][3],但它完全不清楚[1][3]正在访问什么。

import inspect
from types import FrameType
from typing import cast


def demo_the_caller_name() -> str:
    """Return the calling function's name."""
    # Ref: https://stackoverflow.com/a/57712700/
    return cast(FrameType, cast(FrameType, inspect.currentframe()).f_back).f_code.co_name


if __name__ == '__main__':
    def _test_caller_name() -> None:
        assert demo_the_caller_name() == '_test_caller_name'
    _test_caller_name()

注意cast(FrameType, frame)是用来满足mypy的。


致谢:回复请留言1313e。

我提出了一个稍长的版本,试图构建一个完整的方法名称,包括模块和类。

https://gist.github.com/2151727(修订版9CCCBF)

# Public Domain, i.e. feel free to copy/paste
# Considered a hack in Python 2

import inspect

def caller_name(skip=2):
    """Get a name of a caller in the format module.class.method

       `skip` specifies how many levels of stack to skip while getting caller
       name. skip=1 means "who calls me", skip=2 "who calls my caller" etc.

       An empty string is returned if skipped levels exceed stack height
    """
    stack = inspect.stack()
    start = 0 + skip
    if len(stack) < start + 1:
      return ''
    parentframe = stack[start][0]    

    name = []
    module = inspect.getmodule(parentframe)
    # `modname` can be None when frame is executed directly in console
    # TODO(techtonik): consider using __main__
    if module:
        name.append(module.__name__)
    # detect classname
    if 'self' in parentframe.f_locals:
        # I don't know any way to detect call from the object method
        # XXX: there seems to be no way to detect static method call - it will
        #      be just a function call
        name.append(parentframe.f_locals['self'].__class__.__name__)
    codename = parentframe.f_code.co_name
    if codename != '<module>':  # top level usually
        name.append( codename ) # function or a method

    ## Avoid circular refs and frame leaks
    #  https://docs.python.org/2.7/library/inspect.html#the-interpreter-stack
    del parentframe, stack

    return ".".join(name)