我有一个很棒的小功能,看起来像这样:
def verbose_print(message, *args, **kwargs):
"""Prints `message` with a helpful prefix when in verbose mode
Args:
message (str): The message to print. Can be a format string, e.g.
`A %s with some %s in it`
*args: Variables for the message format
**kwargs: Keyword variables for the message format
"""
# Only print when in verbose mode
if not config.verbose:
return
# Ready a prefix for the message
try:
s = inspect.stack()
module_name = inspect.getmodule(s[1][0]).__name__
func_name = s[1][3]
prefix = '### %s->%s' % (module_name, func_name)
except Exception as e:
prefix = '### [stack unavailable]'
if args:
message = message % args
elif kwargs:
message = message % kwargs
print '%s: %s' % (prefix, message)
该功能的关键在于我可以从任何地方用消息调用它,如果我的项目配置文件设置为详细模式,则所有消息都将打印一个有用的前缀以显示它的调用位置。这是一些输出的例子:
### avesta.webserver->check_login: Checking login for client at 127.0.0.1 ### avesta.webserver->check_login: Found credentials cookie with username: tomas, token: blablabla ### avesta.webserver->check_login: Login valid, refreshing session ### avesta.webserver->get_flash_memory: Fetched flash data: None ### avesta.webserver->get: Fetched data from empty path ('previous_values', 'name'), returning '' ### avesta.webserver->get: Fetched data from empty path ('previous_values', 'description'), returning '' ### avesta.webserver->get: Fetched data from empty path ('validation_errors', 'name'), returning ''
格式为“### module-> function:message”。
现在大部分时间非常有帮助,但它并不完美。在上面的示例中,“get”函数实际上是类的绑定方法,但这是不可见的。我想要完成的是当一个函数是一个绑定方法时,我用这种格式打印:
“### module-> ClassName.function”
但问题是:
感谢任何可以帮助我解决问题的答案。
答案 0 :(得分:5)
我认为这很容易,但结果有点复杂。如果您对bound方法有引用,则可以通过boundMethod.im_class.__name__
获取其类名。但是,当你抓住堆栈时,你不能轻易获得对绑定方法的引用,只是为了堆栈帧。
然而一切都没有丢失! inspect
模块可以使用getargvalues
函数从堆栈帧中获取函数参数。你必须依靠惯例来欺骗一点,即方法总是将第一个参数命名为“self”。你可以检查一下,然后从函数的locals
dict中获取“self”值,从那里可以很容易地得到类名。尝试用他的代码替换当前的try
块:
s = inspect.stack()
module_name = inspect.getmodule(s[1][0]).__name__
func_name = s[1][3]
arginfo = inspect.getargvalues(s[1][0])
if len(arginfo.args) > 0 and arginfo.args[0] == "self":
func_name = "%s.%s" (arginfo.locals["self"].__class__.__name__, func_name)
prefix = '### %s->%s' % (module_name, func_name)