如何从解释器堆栈中获取绑定方法的类的名称?

时间:2012-07-28 23:23:11

标签: python class callstack

我有一个很棒的小功能,看起来像这样:

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”

但问题是:

  1. 我只从堆栈中获取函数 name ,所以我无法确定它是否是绑定方法
  2. 即使我有函数引用,我如何推断它所绑定的类名呢?
  3. 感谢任何可以帮助我解决问题的答案。

1 个答案:

答案 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)