Get __name__ of calling function's module in Python
Question:
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?
Answers:
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)
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)
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.
As for me, following line was enough to get callers’name.
import inspect
frame = inspect.stack()[-1]
print(frame.filename)
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?
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)
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)
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.
As for me, following line was enough to get callers’name.
import inspect
frame = inspect.stack()[-1]
print(frame.filename)