问题:在Python中获取调用函数模块的__name__
假设myapp/foo.py
包含:
def info(msg):
caller_name = ????
print '[%s] %s' % (caller_name, msg)
并myapp/bar.py
包含:
import foo
foo.info('Hello') # => [myapp.bar] Hello
在这种情况下,我想caller_name
设置为“ __name__
调用函数”模块的属性(即“ myapp.foo”)。如何才能做到这一点?
回答 0
检出检查模块:
inspect.stack()
将返回堆栈信息。
在函数内部,inspect.stack()[1]
将返回调用者的堆栈。从那里,您可以获得有关调用者的函数名称,模块等的更多信息。
有关详细信息,请参阅文档:
http://docs.python.org/library/inspect.html
此外,Doug Hellmann在他的PyMOTW系列中对检查模块做了很好的撰写:
http://pymotw.com/2/inspect/index.html#module-inspect
编辑:这是一些您想要的代码,我认为:
def info(msg):
frm = inspect.stack()[1]
mod = inspect.getmodule(frm[0])
print '[%s] %s' % (mod.__name__, msg)
回答 1
面对类似的问题,我发现sys模块中的sys._current_frames()包含有趣的信息,这些信息至少在特定的用例中可以帮助您,而无需导入检查。
>>> sys._current_frames()
{4052: <frame object at 0x03200C98>}
然后,您可以使用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__'
对于文件名,您还可以使用f.f_back.f_code.co_filename,如上文Mark Roddy所建议。我不确定此方法的局限性和注意事项(很可能会出现多个线程),但是我打算在自己的情况下使用它。
回答 2
我不建议您这样做,但是您可以使用以下方法来实现您的目标:
def caller_name():
frame=inspect.currentframe()
frame=frame.f_back.f_back
code=frame.f_code
return code.co_filename
然后,如下更新您的现有方法:
def info(msg):
caller = caller_name()
print '[%s] %s' % (caller, msg)