You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python自定义IO类中__getattribute__与__getattr__属性查找异常咨询

自定义IO类属性查找异常分析

自定义代码

import io

class Test(io.BufferedIOBase):
    def __init__(self, f):
        self.f = f

    def __getattr__(self, name):
        print("getattr: searching for: ", name)
        #try:
        #    v = getattr(self.f, name)
        #except Exception:
        #    print("    found nothing!")
        #    raise
        #print("    found:     ", v)
        #return v
        #return 22
        raise AttributeError(name)

    def __getattribute__(self, name):
        print("1.getattribute@self: searching for: ", name, flush=True)
        try:
            v = super().__getattribute__(name)
        except Exception as e:
            print("    1.exception: ", e)
            print("    1.found nothing!", flush=True)
            pass
        else:
            print("    1.found:     ", v, flush=True)
            return v
        print("2.getattribute@self.f: searching for: ", name, flush=True)
        #f = super().__getattribute__("f")
        f = object.__getattribute__(self, "f")
        try:
            v = getattr(f, name)
        except Exception as e:
            print("    2.exception: ", e)
            print("    2.found nothing!", flush=True)
            raise
        else:
            print("    2.found:     ", v, flush=True)
            return v
        print("ERROR")


p = "test_file.bin"  # 假设存在该测试文件
f1 = open(p, "rb")
f2 = Test(f1)
print("\nTest 01:")
v = f2.closed
print("result: ", v)
print("\nTest 02:")
v = f2.qwer
print("result: ", v)

运行结果

Test 01:
1.getattribute@self: searching for:  closed
1.getattribute@self: searching for:  __IOBase_closed
    1.exception:  'Test' object has no attribute '__IOBase_closed'
    1.found nothing!
2.getattribute@self.f: searching for:  __IOBase_closed
    2.exception:  '_io.BufferedReader' object has no attribute '__IOBase_closed'
    2.found nothing!
getattr: searching for:  __IOBase_closed
    1.found:      False
result:  False

Test 02:
1.getattribute@self: searching for:  qwer
    1.exception:  'Test' object has no attribute 'qwer'
    1.found nothing!
2.getattribute@self.f: searching for:  qwer
    2.exception:  '_io.BufferedReader' object has no attribute 'qwer'
    2.found nothing!
getattr: searching for:  qwer
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
Cell In[532], line 49
     47 print("result: ", v)
     48 print("\nTest 02:")
---> 49 v = f2.qwer
     50 print("result: ", v)

Cell In[532], line 15, in Test.__getattr__(self, name)
      6 print("getattr: searching for: ", name)
      7 #try:
      8 #    v = getattr(self.f, name)
      9 #except Exception:
   (...)
     13 #return v
     14 #return 22
---> 15 raise AttributeError(name)

AttributeError: qwer

用户分析与疑问

根据object.__getattribute__()文档,梳理属性查找流程如下:

  1. closed是IOBase中的非数据属性。
  2. 访问该属性时,会在__getattribute__返回前触发内部逻辑,查找self.__closed;按照Python名称修饰规则,这个属性实际应为_IOBase__closed。

实际运行中出现两个异常点:

  1. 自定义__getattribute__的日志显示,程序在查找不存在的__IOBase_closed而非正确的_IOBase__closed,推测是Python与CPython的实现差异导致。
  2. 自定义的__getattribute__和__getattr__均抛出了AttributeError,但最终却成功返回了_IOBase__closed的值,猜测Python调用了MRO中更高层级的属性查找函数,但对这一逻辑存在困惑,希望得到解答。

内容的提问来源于stack exchange,提问作者user19087

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.14 12:07:32