Welcome, guest | Sign In | My Account | Store | Cart

How to obtain the name of a method or a function from within the running method/function.

Acknowledgement: the solution to this problem is given by Christian Tismer (tismer@tismer.com; Mission Impossible 5oftware)

Python, 53 lines
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
# obtaining the name of a function/method
# Christian Tismer
# March 2001

# the following function might be implemented in the
# sys module, when generators are introduced.
# For now, let's emulate it. The way is quite inefficient
# since it uses an exception, but it works.

import sys

def _getframe(level=0):
    try:
        1/0
    except:
        import sys
        tb = sys.exc_info()[-1]
    frame = tb.tb_frame
    while level >= 0:
        frame = frame.f_back
        level = level - 1
    return frame

sys._getframe = _getframe
del _getframe

# we now assume that we have sys._getframe

def funcname():
    return sys._getframe(1).f_code.co_name

class Log:

    def __init__(self):
        self.previous = None

    def methodA(self):
        self.previous = funcname()

    def methodB(self):
        self.previous = funcname()

myinstance = Log()
myinstance.methodA()
print myinstance.previous
myinstance.methodB()
print myinstance.previous

printout="""
methodA
methodB
"""
# that's all folks

4 comments

Jeremy Hylton 20 years, 8 months ago  # | flag

Python 2.1 sys._getframe(). The getframe function described in this recipe is available as a builtin function in Python 2.1. sys._getframe() returns the current frame object.

Tino Lange 19 years, 10 months ago  # | flag

Determining Python Version on import. Hi!

Because sys._getframe() is available for Python > 2.1 I suggest to change the Code like this - so you make sure that noone overwrites the fast Python >= 2.1 -implementation:

if sys.version[:3] < '2.1': # sys.version_info is also not available for early pythons....
    #print 'loading emulated sys._getframe() for Python < 2.1'
    def _getframe(level=0):
        try:
            1/0
        except:
            import sys
            tb = sys.exc_info()[-1]
        frame = tb.tb_frame
        while level >= 0:
            frame = frame.f_back
            level = level - 1
        return frame

    sys._getframe = _getframe
    del _getframe
Sean True 19 years, 8 months ago  # | flag

A mild flaw in this implementation. The reference to tb needs to be eradicated (well known Python lore). I had a case of the reference causing a refcount bump on an object (a lock object) two levels up from the call to getframe(). The increased refcount caused the lock object to persist after it was deleted, which was not expected (or appreciated).

Not a problem with newer Python with native getframe(), I hope.

def getframe(level=0):
     try:
         1/0
     except:
         import sys
         tb = sys.exc_info()[-1]
     frame = tb.tb_frame
     # The next line seems important.
     tb = None
     while level >= 0:
         frame = frame.f_back
         level = level - 1
     return frame

<p>

-- Sean True

Webreply, Inc.

Peter Hansen 19 years, 1 month ago  # | flag

Slightly better approach? Perhaps better than checking the version is simply to test for the existence of the function:

if not hasattr(sys, '_getframe'):
   # do the rest here as before

It's generally better to test for capabilities rather than versions.