37

How can I get a variable that contains the currently executing function in Python? I don't want the function's name. I know I can use inspect.stack to get the current function name. I want the actual callable object. Can this be done without using inspect.stack to retrieve the function's name and then evaling the name to get the callable object?

Edit: I have a reason to do this, but it's not even a remotely good one. I'm using plac to parse command-line arguments. You use it by doing plac.call(main), which generates an ArgumentParser object from the function signature of "main". Inside "main", if there is a problem with the arguments, I want to exit with an error message that includes the help text from the ArgumentParser object, which means that I need to directly access this object by calling plac.parser_from(main).print_help(). It would be nice to be able to say instead: plac.parser_from(get_current_function()).print_help(), so that I am not relying on the function being named "main". Right now, my implementation of "get_current_function" would be:

import inspect    
def get_current_function():
    return eval(inspect.stack()[1][3])

But this implementation relies on the function having a name, which I suppose is not too onerous. I'm never going to do plac.call(lambda ...).

In the long run, it might be more useful to ask the author of plac to implement a print_help method to print the help text of the function that was most-recently called using plac, or something similar.

martineau
  • 119,623
  • 25
  • 170
  • 301
Ryan C. Thompson
  • 40,856
  • 28
  • 97
  • 159
  • 8
    I'll ask. Why do you want to do this? – Kenan Banks Dec 20 '10 at 18:20
  • 1
    I'll suggest. Don't waste time trying to do this. Functions are already first-class objects. – S.Lott Dec 20 '10 at 19:13
  • 20
    Functions being first-class objects is a reason why you *should* be able to get a reference to a function from itself, just as you *should* be able to get a reference to a class you're defining while you're defining it (a much more common request). Neither is supported by Python. This doesn't need to be runtime (eg. inspecting the stack); it can be performed at function binding time (when a function is created from its code object). I'm curious why he wants this too, though (the uses of the class case are much more obvious). – Glenn Maynard Dec 20 '10 at 20:46

10 Answers10

35

The stack frame tells us what code object we're in. If we can find a function object that refers to that code object in its __code__ attribute, we have found the function.

Fortunately, we can ask the garbage collector which objects hold a reference to our code object, and sift through those, rather than having to traverse every active object in the Python world. There are typically only a handful of references to a code object.

Now, functions can share code objects, and do in the case where you return a function from a function, i.e. a closure. When there's more than one function using a given code object, we can't tell which function it is, so we return None.

import inspect, gc

def giveupthefunc():
    frame = inspect.currentframe(1)
    code  = frame.f_code
    globs = frame.f_globals
    functype = type(lambda: 0)
    funcs = []
    for func in gc.get_referrers(code):
        if type(func) is functype:
            if getattr(func, "__code__", None) is code:
                if funcs:
                    return None
                funcs.append(func)
    return funcs[0] if funcs else None

Some test cases:

def foo():
    return giveupthefunc()

zed = lambda: giveupthefunc()

bar, foo = foo, None

print bar()
print zed()

I'm not sure about the performance characteristics of this, but i think it should be fine for your use case.

kindall
  • 178,883
  • 35
  • 278
  • 309
  • 26
    I haven't evaluated your answer for validity yet, but I'm upvoting for "give up the func". – Ryan C. Thompson Dec 22 '10 at 06:25
  • Ok, that's pretty cool. This is exactly what I was looking for. – Ryan C. Thompson Dec 22 '10 at 06:34
  • 6
    As a caveat, this is *very* CPython-specific. – kindall Dec 22 '10 at 06:59
  • 3
    [here](https://gist.github.com/751449)'s a counter example. Like I said in my answer, there are a lot of corner cases. – aaronasterling Dec 22 '10 at 12:28
  • Ah, yeah, that's where functions share code objects... closures. Hm. For now, added a note that that's a corner case. – kindall Dec 22 '10 at 14:52
  • Code now detects this and returns `None` rather than the wrong function. I have another idea which I'll work on later. – kindall Dec 22 '10 at 14:59
  • Doesn't work for me in Py3. Used bukzor's answer successfully. – cfi Mar 30 '12 at 14:34
  • 1
    This strategy works in both CPython and PyPy, across Python 2.6, 2.7, and 3. The trick is changing the attribute names from `func_code` to `__code__` and `func_globals` to `__globals__`. The real gotcha is that it's slow. About 25,000x slower than knowing the function reference. Fine for debugging uses, maybe not so much performance-needing code. The strategy of `eval()`ing a string function name found from the stack is *much* faster, albeit with its own tradeoffs (closures and such). – Jonathan Eunice Sep 06 '17 at 19:45
  • Unfortunately this strategy fails miserably with closures... just try `f = lambda: lambda: None` `assert f().__code__ is f().__code__` `assert f() is not f()` – user541686 Oct 02 '18 at 07:36
  • Hi @kindall. Do you have any idea how to solve [this](https://stackoverflow.com/q/63402581/2326961)? – Géry Ogam Aug 13 '20 at 21:58
  • @Maggyero I don't think that's easily solvable using the `gc` approach. You'd have to inspect bound method objects, and there could be any number of those referring to the method of interest. – kindall Aug 14 '20 at 03:07
  • 1
    "give up the func" is a homophonic pun ("func" sounds like "funk"). When the "funk" is substituted, the phrase ceases to be a procedure reference and instead becomes a cultural reference to the hit song of the same name by Parliament Funkadelic. Puns are common in both the music of Parliament and in Python literature. Although a thematic break with the Pythonic tradition of Monty Python, which may tear the roof off the sucker, the homophonic substitution may remove faults, defects or shortcomings. You know, like arthritis, rheumatism or migraines. \*puts on sunglasses\* – Lorem Ipsum Jan 28 '21 at 18:12
16

I recently spent a lot of time trying to do something like this and ended up walking away from it. There's a lot of corner cases.

If you just want the lowest level of the call stack, you can just reference the name that is used in the def statement. This will be bound to the function that you want through lexical closure.

For example:

def recursive(*args, **kwargs):
    me = recursive

me will now refer to the function in question regardless of the scope that the function is called from so long as it is not redefined in the scope where the definition occurs. Is there some reason why this won't work?

To get a function that is executing higher up the call stack, I couldn't think of anything that can be reliably done.

aaronasterling
  • 68,820
  • 20
  • 127
  • 125
  • 4
    The problem is that redefining the function is common practice in Python, with (but certainly not limited to) decorators. Whether that matters depends on what you're actually doing, of course, but if you really want the function currently executing, then that's not it. – Glenn Maynard Dec 20 '10 at 20:32
  • @Glenn Maynard. Presumably the person that's writing the function that needs to be able to access itself would have control over the enclosing scope to make sure that either (a) such a redefinition did not occur, or (b) if it did occur, the original function was preserved under a different name that could then be used to access it. The bottom of the call stack is easy. – aaronasterling Dec 21 '10 at 00:51
  • 1
    Avoiding the need to do that is usually the reason for asking this question in the first place (that and recursive lambdas, I suppose). – Glenn Maynard Dec 21 '10 at 00:59
  • LOL. This is kinda dumb and simple, but I haven't actually thought of it. This does what I need, thank you. – Leo Ufimtsev Jun 20 '19 at 02:43
16

This is what you asked for, as close as I can come. Tested in python versions 2.4, 2.6, 3.0.

#!/usr/bin/python
def getfunc():
    from inspect import currentframe, getframeinfo
    caller = currentframe().f_back
    func_name = getframeinfo(caller)[2]
    caller = caller.f_back
    from pprint import pprint
    func = caller.f_locals.get(
            func_name, caller.f_globals.get(
                func_name
        )
    )

    return func

def main():
    def inner1():
        def inner2():
            print("Current function is %s" % getfunc())
        print("Current function is %s" % getfunc())
        inner2()
    print("Current function is %s" % getfunc())
    inner1()


#entry point: parse arguments and call main()
if __name__ == "__main__":
    main()

Output:

Current function is <function main at 0x2aec09fe2ed8>
Current function is <function inner1 at 0x2aec09fe2f50>
Current function is <function inner2 at 0x2aec0a0635f0>
bukzor
  • 37,539
  • 11
  • 77
  • 111
  • 4
    This doesn't really offer any advantages over just using the name of that the function is defined with. You're getting the name of the code object which will not be the "name" of the function if any redefinition has occurred. – aaronasterling Dec 21 '10 at 00:52
  • @aaronasterling: That's true (read your other notes about closures/decorators). But he does get it without repeating himself. I agree in not using this beyond demoing some example code where it's nice to print function names... – cfi Mar 22 '12 at 17:06
  • @aaronasterling Sorry if this question is too basic but I was learning from this example. What is the purpose feeding "caller.f_locals.get()" with "func_name" plus "func_name" as seen by globals, instead of just passing func_name alone? Also, what does get() does when you pass two arguments instead of one? – chris from local group Jun 21 '15 at 03:56
  • @chrisfromlocalgroup: `pydoc dict` https://docs.python.org/3.5/library/stdtypes.html#dict.get – bukzor Jun 22 '15 at 17:25
  • @bukzor It all makes sense now, thanks for your help. – chris from local group Jun 23 '15 at 04:54
12

Here's another possibility: a decorator that implicitly passes a reference to the called function as the first argument (similar to self in bound instance methods). You have to decorate each function that you want to receive such a reference, but "explicit is better than implicit" as they say.

Of course, it has all the disadvantage of decorators: another function call slightly degrades performance, and the signature of the wrapped function is no longer visible.

import functools

def gottahavethatfunc(func):

    @functools.wraps(func)
    def wrapper(*args, **kwargs):
        return func(func, *args, **kwargs)

    return wrapper

The test case illustrates that the decorated function still gets the reference to itself even if you change the name to which the function is bound. This is because you're only changing the binding of the wrapper function. It also illustrates its use with a lambda.

@gottahavethatfunc
def quux(me):
    return me

zoom = gottahavethatfunc(lambda me: me)

baz, quux = quux, None

print baz()
print zoom()

When using this decorator with an instance or class method, the method should accept the function reference as the first argument and the traditional self as the second.

class Demo(object):

    @gottahavethatfunc
    def method(me, self):
        return me

print Demo().method()

The decorator relies on a closure to hold the reference to the wrapped function in the wrapper. Creating the closure directly might actually be cleaner, and won't have the overhead of the extra function call:

def my_func():
    def my_func():
        return my_func
    return my_func
my_func = my_func()

Within the inner function, the name my_func always refers to that function; its value does not rely on a global name that may be changed. Then we just "lift" that function to the global namespace, replacing the reference to the outer function. Works in a class too:

class K(object):
    def my_method():
        def my_method(self):
             return my_method
        return my_method
    my_method = my_method()
kindall
  • 178,883
  • 35
  • 278
  • 309
6

I just define in the beginning of each function a "keyword" which is just a reference to the actual name of the function. I just do this for any function, if it needs it or not:

def test():
    this=test
    if not hasattr(this,'cnt'):
        this.cnt=0
    else:
        this.cnt+=1
    print this.cnt
Peter O.
  • 32,158
  • 14
  • 82
  • 96
Florian
  • 61
  • 1
  • 1
  • whoops! I'm getting Undefined variable on your "this = test" line... and why wouldn't I? – mike rodent Jan 20 '13 at 21:52
  • 1
    @mikerodent I suspect you copied and pasted `this=test` but your function is not named test. You have to put the name of the function in there at least once. That is what the OP was trying to avoid. – Bruno Bronosky Feb 25 '14 at 15:41
5

The call stack does not keep a reference to the function itself - although the running frame as a reference to the code object that is the code associated to a given function.

(Functions are objects with code, and some information about their environment, such as closures, name, globals dictionary, doc string, default parameters and so on).

Therefore if you are running a regular function, you are better of using its own name on the globals dictionary to call itself, as has been pointed out.

If you are running some dynamic, or lambda code, in which you can't use the function name, the only solution is to rebuild another function object which re-uses thre currently running code object and call that new function instead.

You will loose a couple of things, like default arguments, and it may be hard to get it working with closures (although it can be done).

I have written a blog post on doing exactly that - calling anonymous functions from within themselves - I hope the code in there can help you:

http://metapython.blogspot.com/2010/11/recursive-lambda-functions.html

On a side note: avoid the use o inspect.stack -- it is too slow, as it rebuilds a lot of information each time it is called. prefer to use inspect.currentframe to deal with code frames instead.

This may sounds complicated, but the code itself is very short - I am pasting it bellow. The post above contains more information on how this works.

from inspect import currentframe
from types import FunctionType

lambda_cache = {}

def myself (*args, **kw):
    caller_frame = currentframe(1)
    code = caller_frame.f_code
    if not code in lambda_cache:
        lambda_cache[code] = FunctionType(code, caller_frame.f_globals)
    return lambda_cache[code](*args, **kw)

if __name__ == "__main__":
    print "Factorial of 5", (lambda n: n * myself(n - 1) if n > 1 else 1)(5)

If you really need the original function itself, the "myself" function above could be made to search on some scopes (like the calling function global dictionary) for a function object which code object would match with the one retrieved from the frame, instead of creating a new function.

jsbueno
  • 99,910
  • 10
  • 151
  • 209
4

sys._getframe(0).f_code returns exactly what you need: the codeobject being executed. Having a code object, you can retrieve a name with codeobject.co_name

muodov
  • 573
  • 6
  • 8
  • 2
    Note from the reference: "This function should be used for internal and specialized purposes only" - because this is not guaranteed to work across different Python implementations. – Craig S. Anderson Oct 31 '15 at 00:06
  • 1
    True, but this kind of metadata will always be implementation-specific by definition. This will work in CPython – muodov Nov 06 '15 at 13:15
1

Here a variation (Python 3.5.1) of the get_referrers() answer, which tries to distinguish between closures that are using the same code object:

import functools
import gc
import inspect

def get_func():
    frame = inspect.currentframe().f_back
    code = frame.f_code
    return [
        referer
        for referer in gc.get_referrers(code)
        if getattr(referer, "__code__", None) is code and
        set(inspect.getclosurevars(referer).nonlocals.items()) <=
        set(frame.f_locals.items())][0]

def f1(x):
    def f2(y):
        print(get_func())
        return x + y
    return f2

f_var1 = f1(1)
f_var1(3)
# <function f1.<locals>.f2 at 0x0000017235CB2C80>
# 4

f_var2 = f1(2)
f_var2(3)
# <function f1.<locals>.f2 at 0x0000017235CB2BF8>
# 5

def f3():
    print(get_func())    

f3()
# <function f3 at 0x0000017235CB2B70>

def wrapper(func):
    functools.wraps(func)
    def wrapped(*args, **kwargs):
        return func(*args, **kwargs)
    return wrapped

@wrapper
def f4():
    print(get_func())    

f4()
# <function f4 at 0x0000017235CB2A60>

f5 = lambda: get_func()    

print(f5())
# <function <lambda> at 0x0000017235CB2950>
Brian Burns
  • 20,575
  • 8
  • 83
  • 77
someone
  • 11
  • 1
1

OK after reading the question and comments again, I think this is a decent test case:

def foo(n):
  """ print numbers from 0 to n """
  if n: foo(n-1)
  print n

g = foo    # assign name 'g' to function object
foo = None # clobber name 'foo' which refers to function object
g(10)      # dies with TypeError because function object tries to call NoneType

I tried solving it by using a decorator to temporarily clobber the global namespace and reassigning the function object to the original name of the function:

def selfbind(f):
   """ Ensures that f's original function name is always defined as f when f is executed """
   oname = f.__name__
   def g(*args, **kwargs):

      # Clobber global namespace
      had_key = None
      if globals().has_key(oname):
         had_key = True
         key = globals()[oname]
      globals()[oname] = g

      # Run function in modified environment
      result = f(*args, **kwargs)

      # Restore global namespace
      if had_key: 
         globals()[oname] = key
      else:
         del globals()[oname]

      return result

   return g

@selfbind
def foo(n):
   if n: foo(n-1)
   print n

g = foo   # assign name 'g' to function object
foo = 2   # calling 'foo' now fails since foo is an int
g(10)     # print from 0..10, even though foo is now an int
print foo # prints 2 (the new value of Foo)

I'm sure I haven't thought through all the use cases. The biggest problem I see is the function object intentionally changing what its own name points to (an operation which would be overwritten by the decorator), but that should be ok as long as the recursive function doesn't redefine its own name in the middle of recursing.

Still not sure I'd ever need to do this, but thinking about was interesting.

Kenan Banks
  • 207,056
  • 34
  • 155
  • 173
  • A few issues come to mind, but the most critical is threads; multiple threads can call the function in parallel, and return from it in a different order than they entered. Also, if the global scope redefines `foo`, it probably did so for a reason; if calling `g` makes a call to something in the global scope that uses `foo` (the integer), it'll break. I'm fairly certain that the only clean way to do this is with language support--a native call that returns the function object. – Glenn Maynard Dec 21 '10 at 00:11
  • Note that if all you (or the OP) want to do is define a recursive function without worrying about it reference to itself being clobbered, you can just nest the recursive function inside another function. – Glenn Maynard Dec 21 '10 at 00:12
0

Correction of my previous answer, because the subdict check already works with "<=" called on dict_items and the additional set() calls result in problems, if there are dict-values which are dicts themself:

import gc
import inspect


def get_func():
    frame = inspect.currentframe().f_back
    code = frame.f_code
    return [
        referer
        for referer in gc.get_referrers(code)
        if getattr(referer, "__code__", None) is code and
        inspect.getclosurevars(referer).nonlocals.items() <=
        frame.f_locals.items()][0]