How to Get the Name of the Calling Function Inside the Called Routine

How to get the name of the calling function inside the called routine?

Thanks @GavinSimpson and @RicardoSporta, but I've figured it out. I'll post an answer in case somebody searches for this in SO.

The name of the function that generated the current call can be retrieved by

deparse(sys.calls()[[sys.nframe()-1]])

This returns a string that contains not only the name of the function, but the entire call object. The name alone can be retrieve by subsetting sys.calls()[[sys.nframe()-1]] before deparsing.

I wanted this because I wrote a function that checks the arguments and halts execution in case of an error. But I wanted this function to (i) dump the environment and (ii) show name of the function one level above in the execution stack. (i) is easy, but I was stuck in (ii).

As for the second question in my post, this is what happens: the expression stop("invalid input") is evaluated in the environment of the test function, but this is not the same thing as if the expression was part of test's body, because the execution stack is different in this 2 scenarios. In the latter case, stop has only test above it, but in the first, it has eval, check and then test upwards. The execution stack, returned by sys.calls() is not the same thing as the enclosing environments. This is what may cause confusion.

How do I find the name of the calling function?

Here are two options:

  1. You can get a full stacktrace (including the name, module, and offset of the calling function) with recent versions of glibc with the GNU backtrace functions. See my answer here for the details. This is probably the easiest thing.

  2. If that isn't exactly what you're looking for, then you might try libunwind, but it's going to involve more work.

Keep in mind that this isn't something you can know statically (as with PRETTY_FUNCTION); you actually have to walk the stack to figure out what function called you. So this isn't something that's really worth doing in ordinary debug printfs. If you want to do more serious debugging or analysis, though, then this might be useful for you.

Get the calling function name from the called function


new StackFrame(1, true).GetMethod().Name

Note that in release builds the compiler might inline the method being called, in which case the above code would return the caller of the caller, so to be safe you should decorate your method with:

[MethodImpl(MethodImplOptions.NoInlining)]

How to get the caller's method name in the called method?

inspect.getframeinfo and other related functions in inspect can help:

>>> import inspect
>>> def f1(): f2()
...
>>> def f2():
... curframe = inspect.currentframe()
... calframe = inspect.getouterframes(curframe, 2)
... print('caller name:', calframe[1][3])
...
>>> f1()
caller name: f1

this introspection is intended to help debugging and development; it's not advisable to rely on it for production-functionality purposes.

How can we know the caller function's name?

There's nothing you can do only in a.

However, with a simple standard macro trick, you can achieve what you want, IIUC showing the name of the caller.

void a()
{
/* Your code */
}

void a_special( char const * caller_name )
{
printf( "a was called from %s", caller_name );
a();
}

#define a() a_special(__func__)

void b()
{
a();
}

Getting the caller function name inside another function in Python?

You can use the inspect module to get the info you want. Its stack method returns a list of frame records.

  • For Python 2 each frame record is a list. The third element in each record is the caller name. What you want is this:

    >>> import inspect
    >>> def f():
    ... print inspect.stack()[1][3]
    ...
    >>> def g():
    ... f()
    ...
    >>> g()
    g

  • For Python 3.5+, each frame record is a named tuple so you need to replace

    print inspect.stack()[1][3]

    with

    print(inspect.stack()[1].function)

    on the above code.

Calling a function as a go routine produces different call stack from go routine as anonymous func

The output you've seen is what one would expect, given the inner workings of the Go runtime system:

  • A goroutine, such as the main one that calls your own main in package main, but also including routines started by go somefunc(), is actually called from some machine-specific startup routine. On the playground that's the one in src/runtime/asm_amd64.s.

  • When you define a closure, such as:

    f := func() {
    // code
    }

    this creates an anonymous function. Calling it:

    f()

    calls that anonymous function, from whatever the caller is. This is true regardless of whether the closure is assigned to a variable (as with f above) or just called right away, or later with defer, or whatever:

    defer func() {
    // code ...
    }()
  • So, writing:

    go func() {
    // code ...
    }()

    simply calls the anonymous function here from that same machine-specific startup. If that function then calls your printCaller function, which uses runtime.Caller(1) to skip over your printCaller function and find its caller, it finds the anonymous function:

    Filename: /tmp/sandbox297971268/prog.go, line: 22

    for instance.

  • But when you write:

    go printCaller()

    you are invoking the function named printCaller from the machine-specific goroutine startup code.

Since printCaller prints the name of its caller, which is this machine-specific startup code, that's what you see.

There's a big caveat here and that is that runtime.Caller is allowed to fail. That's why it returns a boolean ok along with the pc uintptr, file string, line int values. There's no guarantee that the machine-specific assembly caller will be find-able.

Java: How to get the caller function name

You could try

StackTraceElement[] stacktrace = Thread.currentThread().getStackTrace();
StackTraceElement e = stacktrace[2];//maybe this number needs to be corrected
String methodName = e.getMethodName();

Determine function name from within that function (without using traceback)

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.

getting the name of the calling method

You need to instantiate the StackFrame with an appropriate constructor. For example,

Dim stackframe As New Diagnostics.StackFrame(1)

will skip one stack frame (the logging method itself) and get the frame for the caller of that method.

That said - if at all possible, I'd strongly recommend using a standard logging mechanism such as log4net.



Related Topics



Leave a reply



Submit