我正在为一个类实现__getattribute__
。你知道吗
我想注意任何错误的(当然,这意味着失败是意料之中的)提供属性的失败(因为__getattribute__
实现变得非常复杂)。因此,如果我的代码在引发AttributeError
之前无法找到/提供属性,我会记录一个警告。你知道吗
我知道:
__getattribute__
鼓励实现尽可能小而简单。你知道吗__getattribute__
实现的行为不同被认为是错误的。你知道吗try/except
而不是使用hasattr
。你知道吗TL;DR:尽管如此,我还是想检测对__getattribute__
的调用是否是由于hasattr
(而不是“真正”尝试访问该属性)。你知道吗
您可以使用
sys._getframe
来获取调用者框架,使用inspect.getframeinfo
来获取发出调用的代码行,然后使用某种解析机制,例如regex(您不能使用ast.parse
,因为这一行代码通常是一个不完整的语句)来查看hasattr
是否是调用者。它不是很健壮,但在最合理的情况下应该可以工作:这将输出:
这是不可能的,即使通过堆栈检查。
hasattr
在Python调用堆栈中不生成frame对象,因为它是用C编写的,并且试图检查最后一个Python帧来猜测它是否在hasattr
调用的中间被挂起,很容易出现各种各样的误报和误报。你知道吗如果你下定决心要尽最大努力,那么我能想到的最可靠(但仍然脆弱)的麻烦就是用一个Python函数来修补
builtins.hasattr
,这个函数可以生成Python堆栈框架:在
__getattribute__
内调用probably_called_from_hasattr
将测试您的__getattribute__
是否可能是从hasattr
调用的。这避免了假设调用代码使用了名称“hasattr”,或者名称“hasattr”对应于这个特定的__getattribute__
调用,或者hasattr
调用源自Python级别的代码而不是C这里脆弱性的主要来源是,如果有人在monkey补丁程序运行之前保存了对真实的
hasattr
的引用,或者其他人在monkey补丁程序运行之前hasattr
(例如,如果有人将此代码复制粘贴到同一程序中的另一个文件中)。isinstance
检查试图捕捉其他人在我们面前修补hasattr
的大多数情况,但它并不完美。你知道吗另外,如果用C编写的对象上的
hasattr
触发了对对象的属性访问,那么您的__getattribute__
看起来就像是从hasattr
调用的。这是获得假阳性的最可能的方法;上一段中的所有内容都会给出假阴性。您可以通过检查hasattr
帧的f_locals
中的obj
项是否是它应该是的对象来防止这种情况。你知道吗最后,如果您的
__getattribute__
是从装饰程序创建的包装器、子类__getattribute__
或类似的东西调用的,那么即使包装器或重写是从hasattr
调用的,即使您希望它计数,它也不会计为来自hasattr
的调用。你知道吗相关问题 更多 >
编程相关推荐