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

Hub*_*bro 5 python callstack class

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

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)
Run Code Online (Sandbox Code Playgroud)

该函数的要点是我可以从任何地方用消息调用它,如果我的项目配置文件设置为详细模式,所有消息将打印一个有用的前缀以显示它被调用的位置.这是一些输出的例子:

### 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. 我只从堆栈中获取函数名称,所以我无法确定它是否是绑定方法
  2. 即使我有函数引用,我如何推断它绑定的类名?

感谢任何可以帮助我解决这个问题的答案.

Blc*_*ght 5

我认为这很容易,但结果有点复杂.如果您对bound方法有引用,则可以通过它获取其类名boundMethod.im_class.__name__.但是,当你抓住堆栈时,你不能轻易获得对绑定方法的引用,只是为了堆栈帧.

然而一切都没有丢失!该inspect模块可以使用该getargvalues函数从堆栈帧获取函数参数.你必须依靠惯例来欺骗一点,即方法总是将第一个参数命名为"self".你可以检查一下,然后从函数的localsdict中获取"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)
Run Code Online (Sandbox Code Playgroud)