132

Suppose myapp/foo.py contains:

def info(msg):
    caller_name = ????
    print '[%s] %s' % (caller_name, msg)

And myapp/bar.py contains:

import foo
foo.info('Hello') # => [myapp.bar] Hello

I want caller_name to be set to the __name__ attribute of the calling functions' module (which is 'myapp.foo') in this case. How can this be done?

cduck
  • 2,691
  • 6
  • 29
  • 35
Sridhar Ratnakumar
  • 81,433
  • 63
  • 146
  • 187

4 Answers4

168

Check out the inspect module:

inspect.stack() will return the stack information.

Inside a function, inspect.stack()[1] will return your caller's stack. From there, you can get more information about the caller's function name, module, etc.

See the docs for details:

http://docs.python.org/library/inspect.html

Also, Doug Hellmann has a nice writeup of the inspect module in his PyMOTW series:

http://pymotw.com/2/inspect/index.html#module-inspect

EDIT: Here's some code which does what you want, I think:

import inspect 

def info(msg):
    frm = inspect.stack()[1]
    mod = inspect.getmodule(frm[0])
    print '[%s] %s' % (mod.__name__, msg)
Alan W. Smith
  • 24,647
  • 4
  • 70
  • 96
ars
  • 120,335
  • 23
  • 147
  • 134
  • 1
    So how do you get the `__name__` attribute of this module using the `inspect` module? For example, how do I get back `myapp.foo` (not `myapp/foo.py`) in my above example? I already tried using the inspect module before posting at SO. – Sridhar Ratnakumar Jul 08 '09 at 03:38
  • 7
    Be aware that this will interact strangely with import hooks, won't work on ironpython, and may behave in surprising ways on jython. It's best if you can avoid magic like this. – Glyph Jul 09 '09 at 11:24
  • 2
    Also note that keeping a reference to a stack frame can prevent Python's GC from working correctly. See warning here: http://docs.python.org/library/inspect.html#the-interpreter-stack – Kamil Kisiel Nov 09 '10 at 21:58
  • 6
    Note that if the caller function is decorated (@...), you need to access `inspect.stack()[2]` for the real caller. – Amir Ali Akbari Feb 03 '13 at 08:19
  • Also note that this logic fails to work properly when you compile your python code into an exe using pyinstaller. – panofish Oct 16 '14 at 14:18
  • I found this did not work when I was running my python code inside eggs – Andy Smith Mar 11 '15 at 11:23
  • This does not seem to work with lambdas whose name have been set (for instance `f = lambda x: x; f.__name__ = 'my_function'`, can anyone confirm? – Bertrand Caron Oct 19 '17 at 01:29
  • Seems like if have a breakpoint using something like `import ipdb; ipdb.set_trace()`, the location is at the `11th` place, not the `1st`. – alpha_989 Aug 01 '18 at 19:33
  • @AmirAliAkbari Not so. Assuming that the decorator works by calling the original function, `inspect.stack()[1]` refers to the original function; `inspect.stack()[2]` refers to *the decorator*. Since the decorator is doing the calling, it will be lower down on the stack. It can't be above, anyway, because the original function code doesn't know about the decorator. – Karl Knechtel Feb 03 '22 at 16:01
  • You *would* have the problem if you wanted to *use the decorator to call `info` on the decorated function's behalf*, though. – Karl Knechtel Feb 03 '22 at 16:10
30

Confronted with a similar problem, I have found that sys._current_frames() from the sys module contains interesting information that can help you, without the need to import inspect, at least in specific use cases.

>>> sys._current_frames()
{4052: <frame object at 0x03200C98>}

You can then "move up" using f_back :

>>> f = sys._current_frames().values()[0]
>>> # for python3: f = list(sys._current_frames().values())[0]

>>> print f.f_back.f_globals['__file__']
'/base/data/home/apps/apricot/1.6456165165151/caller.py'

>>> print f.f_back.f_globals['__name__']
'__main__'

For the filename you can also use f.f_back.f_code.co_filename, as suggested by Mark Roddy above. I am not sure of the limits and caveats of this method (multiple threads will most likely be a problem) but I intend to use it in my case.

Jason Webster
  • 11
  • 1
  • 2
Louis LC
  • 5,454
  • 1
  • 17
  • 13
  • 2
    note: the inspect.stack code FAILS after compile to exe using pyinstaller, but using sys._current_frames WORKS FINE... so this is the preferred technique for me. – panofish Oct 16 '14 at 14:29
  • 14
    I think it's easier to get the previous frame by [`sys._getframe(1)`](https://docs.python.org/3/library/sys.html#sys._getframe), instead of calling `sys._current_frames()` (btw which returns a frame mapping for every thread). – hooblei Oct 06 '15 at 14:32
  • Thank you hooblei, I haven't tested it yet but seems very useful for multi-threaded situations. – Louis LC Oct 06 '15 at 18:16
  • 1
    I prefer to use [`inspect.currentframe()`](https://docs.python.org/3/library/inspect.html#inspect.currentframe) instead of `sys._current_frames().values()[0]`. – Aran-Fey Apr 28 '18 at 14:09
7

I don't recommend do this, but you can accomplish your goal with the following method:

def caller_name():
    frame=inspect.currentframe()
    frame=frame.f_back.f_back
    code=frame.f_code
    return code.co_filename

Then update your existing method as follows:

def info(msg):
    caller = caller_name()
    print '[%s] %s' % (caller, msg)
Mark Roddy
  • 27,122
  • 19
  • 67
  • 71
3

As for me, following line was enough to get callers'name.

import inspect
frame = inspect.stack()[-1]
print(frame.filename)
Alex Kim
  • 1
  • 2