【问题标题】:get fully qualified method name from inspect stack从检查堆栈中获取完全限定的方法名称
【发布时间】:2013-05-11 11:18:18
【问题描述】:

我无法完成以下功能:

def fullyQualifiedMethodNameInStack(depth=1):
    """
    The function should return <file>_<class>_<method> for the method in the 
    stack at specified depth.
    """
    fileName=inspect.stack()[depth][1]
    methodName=inspect.stack()[depth][3]
    class= """ please help!!! """
    baseName=os.path.splitext( os.path.basename( fileName ) )[0]
    return '{0}_{1}_{2}'.format( baseName, className, methodName )

如您所见,我想要正在执行的方法的类名。 inspect返回的栈只有方法名,不知道如何找到属于该方法的类。

【问题讨论】:

  • 1) 你只能看到函数,不能看到方法,2) 你只能对实例的类型做出有根据的猜测。这与最初定义该方法的类不同。够了吗?
  • 嗯,我希望有可能无需猜测就能找出函数定义在哪个类中。我能做的最有根据的猜测是什么?
  • @MartijnPieters 我对第 2 点很感兴趣。inspect.stack() 似乎始终返回函数名称,而不是函数对象。
  • @millimoose:没错,栈只记录了当前正在执行的函数的名字。这也不一定是访问它的名称。
  • @MartijnPieters 这有点令人惊讶,我本以为实际的函数对象会在某个地方。尽管即使这样也可能并不完美,尤其是考虑到我假设 Python 解释器最终会首先“解包”绑定方法对象。

标签: python


【解决方案1】:

你总是在看一个函数上下文;函数执行时,方法上下文已经消失。从技术上讲,functions act as descriptors 在作为实例 (instance.method_name) 上的属性访问时,会返回一个方法对象。然后,方法对象在被调用时,依次以实例作为第一个参数调用原始函数。因为这一切都发生在 C 代码中,所以原始方法对象的任何痕迹都不会保留在 Python 堆栈上。

堆栈只需要跟踪命名空间和要为本地命名空间执行的代码。这些函数不再需要原始函数对象,只有附加的代码对象仍保留原始函数定义的名称以进行回溯。

如果您知道函数是一个方法,则可以搜索self 本地名称。如果存在,type(self)instance 的类,它不一定是定义该方法的类。

然后您必须搜索类及其基础(循环.__mro__ 属性)以尝试找到定义该方法的类。

您还需要考虑一些障碍:

  • 命名方法的第一个参数self 只是一个约定。如果有人选择了不同的名称,您将无法在不自己解析 Python 源代码的情况下弄清楚这一点,或者在堆栈中再上一步并尝试从 that 行中推断出函数的方式被调用,然后检索方法和它的.im_self 属性。

  • 您只会获得函数的原始名称,在该名称下定义它。这不一定是调用它的名称。函数是一等对象,可以添加到不同名称的类中。

  • 虽然在self 中传递了一个函数并被定义为类定义的一部分,但它可以通过手动 传递self 的值而不是为调用者传入self 引用的方法的通常路径(作为描述符的函数的结果)。

在 Python 3.3 及更高版本中,情况稍好一些;函数对象有一个新的__qualname__ attribute,其中包括类名。那么问题来了,你仍然需要从父栈帧中定位函数对象。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-06-20
    • 2012-07-27
    • 1970-01-01
    • 2021-03-25
    • 2014-06-04
    • 2016-09-30
    • 1970-01-01
    相关资源
    最近更新 更多