【问题标题】:How can I get the name of the class of a bound method from the interpreter stack?如何从解释器堆栈中获取绑定方法的类的名称?
【发布时间】:2012-07-27 04:10:08
【问题描述】:

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

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: 检查客户端在 127.0.0.1 的登录 ### avesta.webserver->check_login:找到用户名:tomas,令牌:blablabla 的凭据 cookie ### avesta.webserver->check_login: 登录有效,刷新会话 ### avesta.webserver->get_flash_memory:获取的闪存数据:无 ### avesta.webserver->get:从空路径('previous_values','name')获取数据,返回'' ### avesta.webserver->get:从空路径('previous_values','description')获取数据,返回'' ### avesta.webserver->get:从空路径('validation_errors','name')获取数据,返回''

格式为"### module->function: message"

现在大多数时候这真的很有帮助,但并不完美。在上面的例子中,“get”函数实际上是一个类的绑定方法,但它是不可见的。我想要完成的是,当一个函数是一个绑定方法时,我用这种格式打印:

"### 模块->ClassName.function"

但问题是:

  1. 我只从堆栈中获取函数 name,所以我无法真正检查它是否是绑定方法
  2. 即使我有函数引用,我如何推断它绑定到的类名?

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

【问题讨论】:

    标签: python class callstack


    【解决方案1】:

    我以为这很容易,但结果有点复杂。如果你有对绑定方法的引用,你可以通过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)
    

    【讨论】:

    • 太棒了!通过检查'self'是否是一个类实例并检查它实际上是否有一个名为func_name的绑定方法,是否可以降低作弊的危险?如果是这样,如何检查这些东西?
    • 可能可以更深入地挖掘并验证第一个参数确实有一个名为func_name 的绑定方法,但我怀疑它是否值得打扰。我认为你更有可能使用这种方法最终得到假阴性(被错误地认为不是方法的函数)而不是假阳性(常规函数错误地成为方法)。那是因为您可以将方法的第一个参数命名为任何名称,self 只是一个约定。嗯,实际上,现在我想起来了,我上面的代码不适用于没有参数的函数。我会编辑来解决这个问题。
    猜你喜欢
    • 2013-05-11
    • 1970-01-01
    • 1970-01-01
    • 2016-03-10
    • 2019-11-04
    • 1970-01-01
    • 1970-01-01
    • 2021-09-02
    • 1970-01-01
    相关资源
    最近更新 更多