Python 3.11子类化文件对象报错:'_io.TextIOWrapper'无'wl'属性
解决自定义文件类中
wl方法调用报错的问题 你遇到的AttributeError: '_io.TextIOWrapper' object has no attribute 'wl',核心原因是:原Open类的__enter__方法返回的是原生文件对象(_io.TextIOWrapper),而非MyOpen类的实例。所以with语句里的outfile其实是原生文件对象,它根本没有你定义的wl方法。
解决方案:修改上下文管理器的返回对象
要让with语句拿到MyOpen的实例,需要修改__enter__方法的返回值,同时调整自定义方法的实现:
方案一:基于原Open类修改
class Open(object): def __init__(self, *args, **kwds): self.args = args self.kwds = kwds def __enter__(self): self.file_obj = open(*self.args, **self.kwds) # 返回当前类实例,而非原生文件对象 return self def __exit__(self, *args): self.file_obj.close() class MyOpen(Open): def wl(self, string): # 直接操作实例的file_obj属性,无需super() self.file_obj.write(string + '\n') # 使用示例 with MyOpen('filename.txt', 'w') as outfile: outfile.wl('some text')
如果需要保留原生文件对象的write、read等方法,可以在MyOpen里添加代理方法:
class MyOpen(Open): def wl(self, string): self.file_obj.write(string + '\n') # 代理原生write方法 def write(self, string): self.file_obj.write(string) # 按需代理其他方法,比如read、readline等
方案二:自定义独立的上下文管理器
如果不想依赖原Open类,可以直接写一个完整的自定义上下文管理器:
class MyOpen: def __init__(self, *args, **kwargs): self.args = args self.kwargs = kwargs self.file_obj = None def __enter__(self): self.file_obj = open(*self.args, **self.kwargs) return self def __exit__(self, exc_type, exc_val, exc_tb): # 确保文件正常关闭 if self.file_obj: self.file_obj.close() def wl(self, string): # 自动添加换行符写入 self.file_obj.write(f"{string}\n") # 可选:代理原生文件方法 def write(self, string): self.file_obj.write(string) # 使用示例 with MyOpen('filename.txt', 'w') as outfile: outfile.wl('some text') outfile.write('直接写入无换行的内容')
关键说明
原Open类的注释里提到“return actual file object so we don't have to worry about proxying”,这是为了避免手动代理原生文件的所有方法,但代价就是无法在上下文变量中使用自定义方法。我们修改返回值后,虽然需要手动代理需要的原生方法,但能实现自定义的wl功能。
内容的提问来源于stack exchange,提问作者sorton9999
相关产品推荐
相关产品推荐

