How do I get the name of a function or method from within a Python function or method?

Question:

I feel like I should know this, but I haven’t been able to figure it out…

I want to get the name of a method–which happens to be an integration test–from inside it so it can print out some diagnostic text. I can, of course, just hard-code the method’s name in the string, but I’d like to make the test a little more DRY if possible.

Asked By: Daryl Spitzer

||

Answers:

I think the traceback module might have what you’re looking for. In particular, the extract_stack function looks like it will do the job.

Answered By: Greg Hewgill

This decorator makes the name of the method available inside the function by passing it as a keyword argument.

from functools import wraps
def pass_func_name(func):
    "Name of decorated function will be passed as keyword arg _func_name"
    @wraps(func)
    def _pass_name(*args, **kwds):
        kwds['_func_name'] = func.func_name
        return func(*args, **kwds)
    return _pass_name

You would use it this way:

@pass_func_name
def sum(a, b, _func_name):
    print "running function %s" % _func_name
    return a + b

print sum(2, 4)

But maybe you’d want to write what you want directly inside the decorator itself. Then the code is an example of a way to get the function name in a decorator. If you give more details about what you want to do in the function, that requires the name, maybe I can suggest something else.

Answered By: nosklo

This seems to be the simplest way using module inspect:

import inspect
def somefunc(a,b,c):
    print "My name is: %s" % inspect.stack()[0][3]

You could generalise this with:

def funcname():
    return inspect.stack()[1][3]

def somefunc(a,b,c):
    print "My name is: %s" % funcname()

Credit to Stefaan Lippens which was found via google.

Answered By: mhawke
# file "foo.py" 
import sys
import os

def LINE( back = 0 ):
    return sys._getframe( back + 1 ).f_lineno
def FILE( back = 0 ):
    return sys._getframe( back + 1 ).f_code.co_filename
def FUNC( back = 0):
    return sys._getframe( back + 1 ).f_code.co_name
def WHERE( back = 0 ):
    frame = sys._getframe( back + 1 )
    return "%s/%s %s()" % ( os.path.basename( frame.f_code.co_filename ),     
                            frame.f_lineno, frame.f_code.co_name )

def testit():
   print "Here in %s, file %s, line %s" % ( FUNC(), FILE(), LINE() )
   print "WHERE says '%s'" % WHERE()

testit()

Output:

$ python foo.py
Here in testit, file foo.py, line 17
WHERE says 'foo.py/18 testit()'

Use “back = 1” to find info regarding two levels back down the stack, etc.

Answered By: Kevin Little

The answers involving introspection via inspect and the like are reasonable. But there may be another option, depending on your situation:

If your integration test is written with the unittest module, then you could use self.id() within your TestCase.

Answered By: spiv

To elaborate on @mhawke’s answer:

Rather than

def funcname():
    return inspect.stack()[1][3]

You can use

def funcname():
    frame = inspect.currentframe().f_back
    return inspect.getframeinfo(frame).function

Which, on my machine, is about 5x faster than the original version according to timeit.

Answered By: A Sz
Categories: questions Tags:
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.